Repository: awslabs/generative-ai-cdk-constructs
Pull request #197 (2024-01-16 00:07:58)

chore(deps): upgrade dependencies
Upgrades project dependencies. See details in [workflow run].

[Workflow Run]: https://github.com/awslabs/generative-ai-cdk-constructs/actions/runs/7535202945

------

*Automatically created by projen via the "upgrade-main" workflow*

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/awslabs/generative-ai-cdk-constructs/pull/197?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=awslabs) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Comparison is base [(`ee64135`)](https://app.codecov.io/gh/awslabs/generative-ai-cdk-constructs/commit/ee6413520c153294bbf601cdee0df21fbcc55e39?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=awslabs) 93.83% compared to head [(`9e1d269`)](https://app.codecov.io/gh/awslabs/generative-ai-cdk-constructs/pull/197?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=awslabs) 93.83%.


<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##             main     #197   +/-   ##
=======================================
  Coverage   93.83%   93.83%           
=======================================
  Files          18       18           
  Lines        5597     5597           
  Branches      122      122           
=======================================
  Hits         5252     5252           
  Misses        345      345           
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/awslabs/generative-ai-cdk-constructs/pull/197?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=awslabs).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=awslabs).


Patch:
diff --git a/package.json b/package.json
index e5917e7..92f6980 100644
--- a/package.json
+++ b/package.json
@@ -71,7 +71,7 @@
     "constructs": "^10.3.0"
   },
   "dependencies": {
-    "cdk-nag": "^2.28.8"
+    "cdk-nag": "^2.28.9"
   },
   "keywords": [
     "aws-cdk",
diff --git a/src/common/helpers/utils.ts b/src/common/helpers/utils.ts
index daa0f99..1508229 100644
--- a/src/common/helpers/utils.ts
+++ b/src/common/helpers/utils.ts
@@ -10,7 +10,9 @@
  *  OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
  *  and limitations under the License.
  */
+import * as crypto from 'crypto';
 import * as cdk from 'aws-cdk-lib';
+import { IConstruct } from 'constructs';
 /**
  * The version of this package
  */
@@ -19,10 +21,14 @@ export const version = require('../../../package.json').version;
 /**
  * @internal This is an internal core function and should not be called directly by Solutions Constructs clients.
  *
- * @summary Creates a physical resource name in the style of the CDK (string+hash) - this value incorporates Stack ID,
- * so it will remain static in multiple updates of a single stack, but will be different in a separate stack instance
+ * @summary Creates a physical resource name in the style of the CDK (string+hash) - this value incorporates Stack ID or
+ * the Stack Name, so it will remain static in multiple updates of a single stack, but will be different in a separate
+ * stack instance.
+ * @param {string} prefix - the prefix to use for the name
  * @param {string[]} parts - the various string components of the name (eg - stackName, solutions construct ID, L2 construct ID)
  * @param {number} maxLength - the longest string that can be returned
+ * @param {boolean} lower - whether to return the name in lowercase or mixed case
+ * @param {IConstruct} resource - the resource that is calling this function (used to extract the stack Name and Node ID)
  * @returns {string} - a string with concatenated parts (truncated if necessary) + a hash of the full concatenated parts
  *
  */
@@ -30,6 +36,8 @@ export function generatePhysicalName(
   prefix: string,
   parts: string[],
   maxLength: number,
+  lower?: boolean,
+  resource?: IConstruct,
 ): string {
   // The result will consist of:
   //    -The prefix - unaltered
@@ -39,10 +47,26 @@ export function generatePhysicalName(
 
   const stackIdGuidLength = 36;
   const prefixLength = prefix.length;
-  const maxPartsLength = maxLength - prefixLength - 1 - stackIdGuidLength; // 1 is the hyphen
+  let maxPartsLength = maxLength - prefixLength - 1 - stackIdGuidLength; // 1 is the hyphen
 
-  // Extract the Stack ID Guid
-  const uniqueStackIdPart = cdk.Fn.select(2, cdk.Fn.split('/', `${cdk.Aws.STACK_ID}`));
+  let uniqueStackIdPart = '';
+  let uniqueStackIdPartLength = stackIdGuidLength;
+  if (maxPartsLength > 2) {
+    // Extract the Stack ID Guid
+    uniqueStackIdPart = cdk.Fn.select(2, cdk.Fn.split('/', `${cdk.Aws.STACK_ID}`));
+  } else if (resource) {
+    const stack = cdk.Stack.of(resource);
+
+    const hashLength = 8;
+    const sha256 = crypto.createHash('sha256')
+      .update(stack.stackName)
+      .update(cdk.Names.nodeUniqueId(resource.node));
+    uniqueStackIdPart = sha256.digest('hex').slice(0, hashLength);
+    uniqueStackIdPartLength = hashLength;
+    maxPartsLength = maxLength - prefixLength - 1 - hashLength; // 1 is the hyphen
+  } else {
+    throw new Error('The resource parameter is required for short names.');
+  }
 
   let allParts: string = '';
 
@@ -55,6 +79,9 @@ export function generatePhysicalName(
     allParts = allParts.substring(0, subStringLength) + allParts.substring(allParts.length - subStringLength);
   }
 
-  const finalName = prefix.toLowerCase() + allParts + '-' + uniqueStackIdPart;
-  return finalName;
+  if (prefix.length + allParts.length + uniqueStackIdPartLength + 1 /* hyphen */ > maxLength) {
+    throw new Error(`The generated name is longer than the maximum length of ${maxLength}`);
+  }
+
+  return prefix.toLowerCase() + (lower ? allParts.toLowerCase() : allParts) + '-' + uniqueStackIdPart;
 }
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 9dfaefd..0b3d281 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1012,16 +1012,16 @@
   integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==
 
 "@types/node@*":
-  version "20.11.0"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.0.tgz#8e0b99e70c0c1ade1a86c4a282f7b7ef87c9552f"
-  integrity sha512-o9bjXmDNcF7GbM4CNQpmi+TutCgap/K3w1JyKgxAjqx41zp9qlIAVFi0IhCNsJcXolEqLWhbFbEeL0PvYm4pcQ==
+  version "20.11.3"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.3.tgz#ac29fba7aeadc74046b02e50758156f4850f1296"
+  integrity sha512-nrlmbvGPNGaj84IJZXMPhQuCMEVTT/hXZMJJG/aIqVL9fKxqk814sGGtJA4GI6hpJSLQjpi6cn0Qx9eOf9SDVg==
   dependencies:
     undici-types "~5.26.4"
 
 "@types/node@^18":
-  version "18.19.6"
-  resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.6.tgz#537beece2c8ad4d9abdaa3b0f428e601eb57dac8"
-  integrity sha512-X36s5CXMrrJOs2lQCdDF68apW4Rfx9ixYMawlepwmE4Anezv/AV2LSpKD1Ub8DAc+urp5bk0BGZ6NtmBitfnsg==
+  version "18.19.7"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.7.tgz#9a5f6ac7ec42a5dff68fe7faf2dd359710de4a12"
+  integrity sha512-IGRJfoNX10N/PfrReRZ1br/7SQ+2vF/tK3KXNwzXz82D32z5dMQEoOlFew18nLSN+vMNcLY4GrKfzwi/yWI8/w==
   dependencies:
     undici-types "~5.26.4"
 
@@ -1053,15 +1053,15 @@
     "@types/yargs-parser" "*"
 
 "@typescript-eslint/eslint-plugin@^6":
-  version "6.18.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.18.1.tgz#0df881a47da1c1a9774f39495f5f7052f86b72e0"
-  integrity sha512-nISDRYnnIpk7VCFrGcu1rnZfM1Dh9LRHnfgdkjcbi/l7g16VYRri3TjXi9Ir4lOZSw5N/gnV/3H7jIPQ8Q4daA==
+  version "6.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.19.0.tgz#db03f3313b57a30fbbdad2e6929e88fc7feaf9ba"
+  integrity sha512-DUCUkQNklCQYnrBSSikjVChdc84/vMPDQSgJTHBZ64G9bA9w0Crc0rd2diujKbTdp6w2J47qkeHQLoi0rpLCdg==
   dependencies:
     "@eslint-community/regexpp" "^4.5.1"
-    "@typescript-eslint/scope-manager" "6.18.1"
-    "@typescript-eslint/type-utils" "6.18.1"
-    "@typescript-eslint/utils" "6.18.1"
-    "@typescript-eslint/visitor-keys" "6.18.1"
+    "@typescript-eslint/scope-manager" "6.19.0"
+    "@typescript-eslint/type-utils" "6.19.0"
+    "@typescript-eslint/utils" "6.19.0"
+    "@typescript-eslint/visitor-keys" "6.19.0"
     debug "^4.3.4"
     graphemer "^1.4.0"
     ignore "^5.2.4"
@@ -1070,46 +1070,46 @@
     ts-api-utils "^1.0.1"
 
 "@typescript-eslint/parser@^6":
-  version "6.18.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.18.1.tgz#3c3987e186b38c77b30b6bfa5edf7c98ae2ec9d3"
-  integrity sha512-zct/MdJnVaRRNy9e84XnVtRv9Vf91/qqe+hZJtKanjojud4wAVy/7lXxJmMyX6X6J+xc6c//YEWvpeif8cAhWA==
-  dependencies:
-    "@typescript-eslint/scope-manager" "6.18.1"
-    "@typescript-eslint/types" "6.18.1"
-    "@typescript-eslint/typescript-estree" "6.18.1"
-    "@typescript-eslint/visitor-keys" "6.18.1"
+  version "6.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.19.0.tgz#80344086f362181890ade7e94fc35fe0480bfdf5"
+  integrity sha512-1DyBLG5SH7PYCd00QlroiW60YJ4rWMuUGa/JBV0iZuqi4l4IK3twKPq5ZkEebmGqRjXWVgsUzfd3+nZveewgow==
+  dependencies:
+    "@typescript-eslint/scope-manager" "6.19.0"
+    "@typescript-eslint/types" "6.19.0"
+    "@typescript-eslint/typescript-estree" "6.19.0"
+    "@typescript-eslint/visitor-keys" "6.19.0"
     debug "^4.3.4"
 
-"@typescript-eslint/scope-manager@6.18.1":
-  version "6.18.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.18.1.tgz#28c31c60f6e5827996aa3560a538693cb4bd3848"
-  integrity sha512-BgdBwXPFmZzaZUuw6wKiHKIovms97a7eTImjkXCZE04TGHysG+0hDQPmygyvgtkoB/aOQwSM/nWv3LzrOIQOBw==
+"@typescript-eslint/scope-manager@6.19.0":
+  version "6.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.19.0.tgz#b6d2abb825b29ab70cb542d220e40c61c1678116"
+  integrity sha512-dO1XMhV2ehBI6QN8Ufi7I10wmUovmLU0Oru3n5LVlM2JuzB4M+dVphCPLkVpKvGij2j/pHBWuJ9piuXx+BhzxQ==
   dependencies:
-    "@typescript-eslint/types" "6.18.1"
-    "@typescript-eslint/visitor-keys" "6.18.1"
+    "@typescript-eslint/types" "6.19.0"
+    "@typescript-eslint/visitor-keys" "6.19.0"
 
-"@typescript-eslint/type-utils@6.18.1":
-  version "6.18.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.18.1.tgz#115cf535f8b39db8301677199ce51151e2daee96"
-  integrity sha512-wyOSKhuzHeU/5pcRDP2G2Ndci+4g653V43gXTpt4nbyoIOAASkGDA9JIAgbQCdCkcr1MvpSYWzxTz0olCn8+/Q==
+"@typescript-eslint/type-utils@6.19.0":
+  version "6.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.19.0.tgz#522a494ef0d3e9fdc5e23a7c22c9331bbade0101"
+  integrity sha512-mcvS6WSWbjiSxKCwBcXtOM5pRkPQ6kcDds/juxcy/727IQr3xMEcwr/YLHW2A2+Fp5ql6khjbKBzOyjuPqGi/w==
   dependencies:
-    "@typescript-eslint/typescript-estree" "6.18.1"
-    "@typescript-eslint/utils" "6.18.1"
+    "@typescript-eslint/typescript-estree" "6.19.0"
+    "@typescript-eslint/utils" "6.19.0"
     debug "^4.3.4"
     ts-api-utils "^1.0.1"
 
-"@typescript-eslint/types@6.18.1":
-  version "6.18.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.18.1.tgz#91617d8080bcd99ac355d9157079970d1d49fefc"
-  integrity sha512-4TuMAe+tc5oA7wwfqMtB0Y5OrREPF1GeJBAjqwgZh1lEMH5PJQgWgHGfYufVB51LtjD+peZylmeyxUXPfENLCw==
+"@typescript-eslint/types@6.19.0":
+  version "6.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.19.0.tgz#689b0498c436272a6a2059b09f44bcbd90de294a"
+  integrity sha512-lFviGV/vYhOy3m8BJ/nAKoAyNhInTdXpftonhWle66XHAtT1ouBlkjL496b5H5hb8dWXHwtypTqgtb/DEa+j5A==
 
-"@typescript-eslint/typescript-estree@6.18.1":
-  version "6.18.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.18.1.tgz#a12b6440175b4cbc9d09ab3c4966c6b245215ab4"
-  integrity sha512-fv9B94UAhywPRhUeeV/v+3SBDvcPiLxRZJw/xZeeGgRLQZ6rLMG+8krrJUyIf6s1ecWTzlsbp0rlw7n9sjufHA==
+"@typescript-eslint/typescript-estree@6.19.0":
+  version "6.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.19.0.tgz#0813ba364a409afb4d62348aec0202600cb468fa"
+  integrity sha512-o/zefXIbbLBZ8YJ51NlkSAt2BamrK6XOmuxSR3hynMIzzyMY33KuJ9vuMdFSXW+H0tVvdF9qBPTHA91HDb4BIQ==
   dependencies:
-    "@typescript-eslint/types" "6.18.1"
-    "@typescript-eslint/visitor-keys" "6.18.1"
+    "@typescript-eslint/types" "6.19.0"
+    "@typescript-eslint/visitor-keys" "6.19.0"
     debug "^4.3.4"
     globby "^11.1.0"
     is-glob "^4.0.3"
@@ -1117,25 +1117,25 @@
     semver "^7.5.4"
     ts-api-utils "^1.0.1"
 
-"@typescript-eslint/utils@6.18.1":
-  version "6.18.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.18.1.tgz#3451cfe2e56babb6ac657e10b6703393d4b82955"
-  integrity sha512-zZmTuVZvD1wpoceHvoQpOiewmWu3uP9FuTWo8vqpy2ffsmfCE8mklRPi+vmnIYAIk9t/4kOThri2QCDgor+OpQ==
+"@typescript-eslint/utils@6.19.0":
+  version "6.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.19.0.tgz#557b72c3eeb4f73bef8037c85dae57b21beb1a4b"
+  integrity sha512-QR41YXySiuN++/dC9UArYOg4X86OAYP83OWTewpVx5ct1IZhjjgTLocj7QNxGhWoTqknsgpl7L+hGygCO+sdYw==
   dependencies:
     "@eslint-community/eslint-utils" "^4.4.0"
     "@types/json-schema" "^7.0.12"
     "@types/semver" "^7.5.0"
-    "@typescript-eslint/scope-manager" "6.18.1"
-    "@typescript-eslint/types" "6.18.1"
-    "@typescript-eslint/typescript-estree" "6.18.1"
+    "@typescript-eslint/scope-manager" "6.19.0"
+    "@typescript-eslint/types" "6.19.0"
+    "@typescript-eslint/typescript-estree" "6.19.0"
     semver "^7.5.4"
 
-"@typescript-eslint/visitor-keys@6.18.1":
-  version "6.18.1"
-  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.18.1.tgz#704d789bda2565a15475e7d22f145b8fe77443f4"
-  integrity sha512-/kvt0C5lRqGoCfsbmm7/CwMqoSkY3zzHLIjdhHZQW3VFrnz7ATecOHR7nb7V+xn4286MBxfnQfQhAmCI0u+bJA==
+"@typescript-eslint/visitor-keys@6.19.0":
+  version "6.19.0"
+  resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.19.0.tgz#4565e0ecd63ca1f81b96f1dd76e49f746c6b2b49"
+  integrity sha512-hZaUCORLgubBvtGpp1JEFEazcuEdfxta9j4iUwdSAr7mEsYYAp3EAUyCZk3VEEqGj6W+AV4uWyrDGtrlawAsgQ==
   dependencies:
-    "@typescript-eslint/types" "6.18.1"
+    "@typescript-eslint/types" "6.19.0"
     eslint-visitor-keys "^3.4.1"
 
 "@ungap/structured-clone@^1.2.0":
@@ -1523,10 +1523,10 @@ case@1.6.3, case@^1.6.3:
   resolved "https://registry.yarnpkg.com/case/-/case-1.6.3.tgz#0a4386e3e9825351ca2e6216c60467ff5f1ea1c9"
   integrity sha512-mzDSXIPaFwVDvZAHqZ9VlbyF4yyXRuX6IvB06WvPYkqJVO24kX1PPhv9bfpKNFZyxYFmmgo03HUiD8iklmJYRQ==
 
-cdk-nag@^2.28.8:
-  version "2.28.8"
-  resolved "https://registry.yarnpkg.com/cdk-nag/-/cdk-nag-2.28.8.tgz#c70f97abdfe240140db1803425bb24abf8880cae"
-  integrity sha512-5zDX+LSvCpmdH/0MYuNw+qstkAzlr68t5tqvMvcQv/lhbZXuuPzFlVew8f2E474sBTrHCmDLtb4rf+7DAxGYGA==
+cdk-nag@^2.28.9:
+  version "2.28.9"
+  resolved "https://registry.yarnpkg.com/cdk-nag/-/cdk-nag-2.28.9.tgz#015a3354096374f1a5e0414f0e34b1aa22686b21"
+  integrity sha512-H24sjfyCW/nYQa4L2fBhwNVl7YMO3jrBQgHa5zyiBMy1QpmceLVyP5A3jU48F72GZsaDMq0Vd+7lx4ZUht0f/g==
 
 chalk@^2.4.2:
   version "2.4.2"
@@ -2080,9 +2080,9 @@ downlevel-dts@^0.11.0:
     typescript next
 
 electron-to-chromium@^1.4.601:
-  version "1.4.630"
-  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.630.tgz#1d9f4169653784997bec98975e11a2c05214ce39"
-  integrity sha512-osHqhtjojpCsACVnuD11xO5g9xaCyw7Qqn/C2KParkMv42i8jrJJgx3g7mkHfpxwhy9MnOJr8+pKOdZ7qzgizg==
+  version "1.4.631"
+  resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.631.tgz#db2de2e1ce90fc1785b5c3f49fde594413270e05"
+  integrity sha512-g73CJB/rMPjdxpiNJYmV1homV7mLVUNe/R0z/HhqMfpjkt58FpYmkTjbtuv3zymdbTTJ+VOEqe1c+lkTjSOhmQ==
 
 emittery@^0.13.1:
   version "0.13.1"
@@ -4575,12 +4575,12 @@ run-parallel@^1.1.9:
     queue-microtask "^1.2.2"
 
 safe-array-concat@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c"
-  integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692"
+  integrity sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==
   dependencies:
-    call-bind "^1.0.2"
-    get-intrinsic "^1.2.1"
+    call-bind "^1.0.5"
+    get-intrinsic "^1.2.2"
     has-symbols "^1.0.3"
     isarray "^2.0.5"
 


Test patch:
diff --git a/test/common/helpers/utils.test.ts b/test/common/helpers/utils.test.ts
new file mode 100644
index 0000000..52ddacd
--- /dev/null
+++ b/test/common/helpers/utils.test.ts
@@ -0,0 +1,108 @@
+/**
+ *  Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
+ *  with the License. A copy of the License is located at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
+ *  OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
+ *  and limitations under the License.
+ */
+import * as cdk from 'aws-cdk-lib';
+import { generatePhysicalName } from '../../../src/common/helpers/utils';
+
+
+describe('generatePhysicalName', () => {
+  let testResourceA: TestResource;
+  let testResourceB: TestResource;
+  let testStack: cdk.Stack;
+
+  afterAll(() => {
+    console.log('Test completed');
+  });
+
+  beforeAll(() => {
+    const app = new cdk.App();
+    testStack = new cdk.Stack(app, 'TestStack', { env: { account: '012345678912', region: 'bermuda-triangle-1' } });
+
+    testResourceA = new TestResource(testStack, 'A');
+    testResourceB = new TestResource(testResourceA, 'B');
+  });
+
+  test('short physical name', () => {
+    const nameA = generatePhysicalName(
+      'testPrefix',
+      ['Foo', 'Bar', 'Baz'],
+      32,
+      true,
+      testResourceA,
+    );
+    const nameB = generatePhysicalName(
+      'testPrefix',
+      ['Foo', 'Bar', 'Baz'],
+      32,
+      true,
+      testResourceB,
+    );
+    expect(nameA).toEqual('testprefixfoobarbaz-900740fe');
+    expect(nameB).toEqual('testprefixfoobarbaz-99f0d580');
+    expect(nameA).not.toEqual(nameB);
+    expect(nameA.length).toBeLessThanOrEqual(32);
+    expect(nameB.length).toBeLessThanOrEqual(32);
+  });
+
+  test('long physical name', () => {
+    const maxLogGroupNameLength = 255;
+    const logGroupPrefix = '/aws/vendedlogs/states/constructs/';
+    const maxGeneratedNameLength = maxLogGroupNameLength - logGroupPrefix.length;
+    const nameParts: string[] = [
+      testStack.stackName, // Name of the stack
+      'StateMachineLogRag', // Literal string for log group name portion
+    ];
+    const logGroupName = generatePhysicalName(logGroupPrefix, nameParts, maxGeneratedNameLength);
+    expect(logGroupName).toMatch(new RegExp('^/aws/vendedlogs/states/constructs/TestStackStateMachineLogRag-\\$\{Token\[TOKEN\.[0-9]+\]\}$'));
+    expect(logGroupName.length).toBeLessThanOrEqual(maxLogGroupNameLength);
+  });
+
+  test('lowercase long physical name', () => {
+    const maxLogGroupNameLength = 255;
+    const logGroupPrefix = '/aws/vendedlogs/states/constructs/';
+    const maxGeneratedNameLength = maxLogGroupNameLength - logGroupPrefix.length;
+    const nameParts: string[] = [
+      testStack.stackName, // Name of the stack
+      'StateMachineLogRag', // Literal string for log group name portion
+    ];
+    const logGroupName = generatePhysicalName(logGroupPrefix, nameParts, maxGeneratedNameLength, true);
+    expect(logGroupName).toMatch(new RegExp('^/aws/vendedlogs/states/constructs/teststackstatemachinelograg-\\$\{Token\[TOKEN\.[0-9]+\]\}$'));
+    expect(logGroupName.length).toBeLessThanOrEqual(maxLogGroupNameLength);
+  });
+
+  test('short name with no resource', () => {
+    expect(() => {
+      generatePhysicalName(
+        'test',
+        ['Foo', 'Bar', 'Baz'],
+        32,
+        true,
+      );
+    },
+    ).toThrow('The resource parameter is required for short names.');
+  });
+
+  test('name too long', () => {
+    expect(() => {
+      generatePhysicalName(
+        '/aws/vendedlogs/states/constructs/',
+        ['Foo', 'Bar', 'Baz'],
+        32,
+        true,
+        testResourceA,
+      );
+    }).toThrow('The generated name is longer than the maximum length of');
+  });
+});
+
+
+class TestResource extends cdk.Resource {}
\ No newline at end of file