name: 测试 Cache State Action on: workflow_dispatch: inputs: test_scope: description: '选择测试范围' required: true default: 'basic' type: choice options: - basic - operations - edge-cases - expiry - delete - full - stress test_prefix: description: '测试缓存前缀' required: false default: 'test-state' clean_cache: description: '清理测试缓存' required: false default: false type: boolean env: TEST_RUN_ID: ${{ github.run_id }} TEST_RUN_NUMBER: ${{ github.run_number }} jobs: # 基础功能测试 test-basic-operations: if: ${{ inputs.test_scope == 'basic' || inputs.test_scope == 'full' }} runs-on: ubuntu-node-20 outputs: test-value: ${{ steps.basic-test.outputs.state-value }} cache-hit: ${{ steps.basic-test.outputs.cache-hit }} steps: - name: 检出代码 uses: actions/checkout@v4 - name: 基础 get-or-set 操作测试 id: basic-test uses: actions/xgj/cache-state@v1 with: state-key: 'basic-test-${{ env.TEST_RUN_ID }}' state-value: 'test-value-${{ env.TEST_RUN_NUMBER }}' default-value: 'default-value' cache-prefix: ${{ inputs.test_prefix }} action: 'get-or-set' - name: 验证基础操作结果 run: | echo "🔍 验证基础操作结果..." echo "状态值: ${{ steps.basic-test.outputs.state-value }}" echo "缓存命中: ${{ steps.basic-test.outputs.cache-hit }}" echo "使用默认值: ${{ steps.basic-test.outputs.used-default }}" echo "缓存键: ${{ steps.basic-test.outputs.cache-key }}" # 验证输出值不为空 if [[ -z "${{ steps.basic-test.outputs.state-value }}" ]]; then echo "❌ 状态值为空" exit 1 fi # 验证缓存键格式(runner.os 在 ubuntu 运行器上返回 "Linux") if [[ "${{ steps.basic-test.outputs.cache-key }}" =~ ^Linux-.*-basic-test-.* ]]; then echo "✅ 缓存键格式正确" else echo "❌ 缓存键格式不正确: ${{ steps.basic-test.outputs.cache-key }}" exit 1 fi echo "✅ 基础操作测试通过" # 操作类型专项测试 test-operation-types: if: ${{ inputs.test_scope == 'operations' || inputs.test_scope == 'full' }} runs-on: ubuntu-node-20 strategy: matrix: operation: [get, set, get-or-set] include: - operation: get test_key: 'get-test' test_value: '' expected_default: 'true' - operation: set test_key: 'set-test' test_value: 'set-value' expected_default: 'false' - operation: get-or-set test_key: 'get-or-set-test' test_value: 'get-or-set-value' expected_default: 'false' steps: - name: 检出代码 uses: actions/checkout@v4 - name: 测试 ${{ matrix.operation }} 操作 id: operation-test uses: actions/xgj/cache-state@v1 with: state-key: '${{ matrix.test_key }}-${{ env.TEST_RUN_ID }}' state-value: ${{ matrix.test_value }} default-value: 'operation-default' cache-prefix: ${{ inputs.test_prefix }} action: ${{ matrix.operation }} - name: 验证 ${{ matrix.operation }} 操作结果 run: | echo "🎯 验证 ${{ matrix.operation }} 操作结果..." echo "状态值: ${{ steps.operation-test.outputs.state-value }}" echo "缓存命中: ${{ steps.operation-test.outputs.cache-hit }}" echo "使用默认值: ${{ steps.operation-test.outputs.used-default }}" # 验证操作特定的逻辑 case "${{ matrix.operation }}" in "get") if [[ "${{ steps.operation-test.outputs.used-default }}" == "${{ matrix.expected_default }}" ]]; then echo "✅ get 操作正确使用默认值" else echo "❌ get 操作默认值行为异常" exit 1 fi ;; "set") if [[ "${{ steps.operation-test.outputs.state-value }}" == "${{ matrix.test_value }}" ]]; then echo "✅ set 操作正确设置值" else echo "❌ set 操作值不匹配" exit 1 fi ;; "get-or-set") if [[ -n "${{ steps.operation-test.outputs.state-value }}" ]]; then echo "✅ get-or-set 操作返回了值" else echo "❌ get-or-set 操作未返回值" exit 1 fi ;; esac echo "✅ ${{ matrix.operation }} 操作测试通过" # 缓存行为测试 test-cache-behavior: if: ${{ inputs.test_scope == 'operations' || inputs.test_scope == 'full' }} runs-on: ubuntu-node-20 steps: - name: 检出代码 uses: actions/checkout@v4 - name: 第一次设置状态 id: first-set uses: actions/xgj/cache-state@v1 with: state-key: 'cache-behavior-test-${{ env.TEST_RUN_ID }}' state-value: 'first-value' cache-prefix: ${{ inputs.test_prefix }} action: 'set' - name: 第一次获取状态 id: first-get uses: actions/xgj/cache-state@v1 with: state-key: 'cache-behavior-test-${{ env.TEST_RUN_ID }}' default-value: 'should-not-use' cache-prefix: ${{ inputs.test_prefix }} action: 'get' - name: 验证缓存命中 run: | echo "🗄️ 验证缓存行为..." echo "第一次设置缓存命中: ${{ steps.first-set.outputs.cache-hit }}" echo "第一次获取缓存命中: ${{ steps.first-get.outputs.cache-hit }}" echo "获取到的值: ${{ steps.first-get.outputs.state-value }}" echo "是否使用默认值: ${{ steps.first-get.outputs.used-default }}" # 验证设置操作不应该命中缓存(第一次) if [[ "${{ steps.first-set.outputs.cache-hit }}" == "false" ]]; then echo "✅ 第一次设置正确未命中缓存" else echo "❌ 第一次设置不应该命中缓存" exit 1 fi # 验证获取操作应该命中缓存 if [[ "${{ steps.first-get.outputs.cache-hit }}" == "true" ]]; then echo "✅ 获取操作正确命中缓存" else echo "❌ 获取操作应该命中缓存" exit 1 fi # 验证获取到的值正确 if [[ "${{ steps.first-get.outputs.state-value }}" == "first-value" ]]; then echo "✅ 获取到正确的缓存值" else echo "❌ 缓存值不匹配,期望: first-value,实际: ${{ steps.first-get.outputs.state-value }}" exit 1 fi # 验证没有使用默认值 if [[ "${{ steps.first-get.outputs.used-default }}" == "false" ]]; then echo "✅ 正确未使用默认值" else echo "❌ 不应该使用默认值" exit 1 fi echo "✅ 缓存行为测试通过" - name: 更新缓存状态 id: update-cache uses: actions/xgj/cache-state@v1 with: state-key: 'cache-behavior-test-${{ env.TEST_RUN_ID }}' state-value: 'updated-value' cache-prefix: ${{ inputs.test_prefix }} action: 'set' - name: 验证缓存更新 id: verify-update uses: actions/xgj/cache-state@v1 with: state-key: 'cache-behavior-test-${{ env.TEST_RUN_ID }}' default-value: 'should-not-use' cache-prefix: ${{ inputs.test_prefix }} action: 'get' - name: 验证更新结果 run: | echo "🔄 验证缓存更新..." echo "更新后的值: ${{ steps.verify-update.outputs.state-value }}" if [[ "${{ steps.verify-update.outputs.state-value }}" == "updated-value" ]]; then echo "✅ 缓存更新成功" else echo "❌ 缓存更新失败,期望: updated-value,实际: ${{ steps.verify-update.outputs.state-value }}" exit 1 fi # 边界情况测试 test-edge-cases: if: ${{ inputs.test_scope == 'edge-cases' || inputs.test_scope == 'full' }} runs-on: ubuntu-node-20 strategy: matrix: edge_case: - name: empty-values state_key: 'empty-test' state_value: '' default_value: '' - name: special-chars state_key: 'special-chars-test' state_value: 'value-with-special-chars' default_value: 'default-special' - name: long-values state_key: 'long-value-test' state_value: 'long-value-with-multiple-words-and-hyphens' default_value: 'long-default-value' - name: unicode state_key: 'unicode-test' state_value: 'unicode-value-test' default_value: 'unicode-default' steps: - name: 检出代码 uses: actions/checkout@v4 - name: 测试边界情况 - ${{ matrix.edge_case.name }} id: edge-test uses: actions/xgj/cache-state@v1 with: state-key: '${{ matrix.edge_case.state_key }}-${{ env.TEST_RUN_ID }}' state-value: ${{ matrix.edge_case.state_value }} default-value: ${{ matrix.edge_case.default_value }} cache-prefix: ${{ inputs.test_prefix }} action: 'get-or-set' - name: 验证边界情况 - ${{ matrix.edge_case.name }} run: | echo "🔬 验证边界情况: ${{ matrix.edge_case.name }}" echo "状态值: '${{ steps.edge-test.outputs.state-value }}'" echo "缓存命中: ${{ steps.edge-test.outputs.cache-hit }}" echo "使用默认值: ${{ steps.edge-test.outputs.used-default }}" echo "缓存键: ${{ steps.edge-test.outputs.cache-key }}" # 验证操作没有失败 if [[ "$?" -eq 0 ]]; then echo "✅ 边界情况 ${{ matrix.edge_case.name }} 处理成功" else echo "❌ 边界情况 ${{ matrix.edge_case.name }} 处理失败" exit 1 fi - name: 额外测试 - 动态特殊字符处理 if: matrix.edge_case.name == 'special-chars' uses: actions/xgj/cache-state@v1 with: state-key: 'dynamic-special-@#$%^&*()' state-value: 'dynamic-value-!@#$%^&*()' default-value: 'dynamic-default-!@#$' cache-prefix: ${{ inputs.test_prefix }} action: 'get-or-set' - name: 额外测试 - 动态长字符串处理 if: matrix.edge_case.name == 'long-values' uses: actions/xgj/cache-state@v1 with: state-key: 'dynamic-very-long-state-key-with-many-words-and-characters-to-test-system-limits' state-value: 'this-is-an-extremely-long-value-that-contains-multiple-words-hyphens-numbers-123456789-and-various-characters-to-thoroughly-test-the-handling-of-long-strings-in-our-cache-state-action' default-value: 'long-fallback-default-value-for-testing-purposes' cache-prefix: ${{ inputs.test_prefix }} action: 'get-or-set' - name: 额外测试 - 动态 Unicode 处理 if: matrix.edge_case.name == 'unicode' uses: actions/xgj/cache-state@v1 with: state-key: 'unicode-测试-中文-🚀-emoji' state-value: 'unicode-值-包含中文-🎯-和emoji-符号' default-value: 'unicode-默认值-包含中文' cache-prefix: ${{ inputs.test_prefix }} action: 'get-or-set' # 并发测试 test-concurrent: if: ${{ inputs.test_scope == 'stress' || inputs.test_scope == 'full' }} runs-on: ubuntu-node-20 strategy: matrix: worker: [1, 2, 3, 4, 5] steps: - name: 检出代码 uses: actions/checkout@v4 - name: 并发操作测试 - Worker ${{ matrix.worker }} id: concurrent-test uses: actions/xgj/cache-state@v1 with: state-key: 'concurrent-test-${{ matrix.worker }}' state-value: 'worker-${{ matrix.worker }}-value-${{ env.TEST_RUN_ID }}' default-value: 'concurrent-default-${{ matrix.worker }}' cache-prefix: ${{ inputs.test_prefix }} action: 'get-or-set' - name: 验证并发操作 run: | echo "🔀 并发操作 Worker ${{ matrix.worker }} 结果:" echo "状态值: ${{ steps.concurrent-test.outputs.state-value }}" echo "缓存命中: ${{ steps.concurrent-test.outputs.cache-hit }}" echo "使用默认值: ${{ steps.concurrent-test.outputs.used-default }}" # 验证值包含正确的 worker 标识 if [[ "${{ steps.concurrent-test.outputs.state-value }}" =~ worker-${{ matrix.worker }} ]]; then echo "✅ Worker ${{ matrix.worker }} 值正确" else echo "❌ Worker ${{ matrix.worker }} 值异常" exit 1 fi # 过期时间测试 test-expiry: if: ${{ inputs.test_scope == 'expiry' || inputs.test_scope == 'full' }} runs-on: ubuntu-node-20 steps: - name: 检出代码 uses: actions/checkout@v4 - name: 测试基础过期功能 - 短期缓存 id: short-expiry uses: actions/xgj/cache-state@v1 with: state-key: 'short-expiry-test-${{ github.run_id }}' state-value: 'short-value' default-value: 'default-short' expiry-seconds: '120' # 2分钟 cache-prefix: ${{ inputs.test_prefix }} - name: 验证短期缓存设置 run: | echo "🕐 短期缓存测试结果:" echo "状态值: ${{ steps.short-expiry.outputs.state-value }}" echo "缓存命中: ${{ steps.short-expiry.outputs.cache-hit }}" echo "过期状态: ${{ steps.short-expiry.outputs.expired }}" echo "缓存键: ${{ steps.short-expiry.outputs.cache-key }}" # 验证缓存键包含时间窗口(永不过期缓存键格式:Linux-test-state-short-expiry-test-1038,有过期时间格式:Linux-test-state-short-expiry-test-1038-12345) # 检查是否有额外的时间窗口后缀(在run_id之后) if [[ "${{ steps.short-expiry.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then echo "✅ 缓存键包含时间窗口标识" else echo "❌ 缓存键缺少时间窗口标识: ${{ steps.short-expiry.outputs.cache-key }}" echo "期望格式: Linux-test-state-short-expiry-test-{run_id}-{time_window}" exit 1 fi - name: 测试永不过期缓存 id: no-expiry uses: actions/xgj/cache-state@v1 with: state-key: 'no-expiry-test-${{ github.run_id }}' state-value: 'permanent-value' default-value: 'default-permanent' expiry-seconds: '0' # 永不过期 cache-prefix: ${{ inputs.test_prefix }} - name: 验证永不过期缓存 run: | echo "♾️ 永不过期缓存测试结果:" echo "状态值: ${{ steps.no-expiry.outputs.state-value }}" echo "缓存命中: ${{ steps.no-expiry.outputs.cache-hit }}" echo "过期状态: ${{ steps.no-expiry.outputs.expired }}" echo "缓存键: ${{ steps.no-expiry.outputs.cache-key }}" # 验证缓存键不包含时间窗口(永不过期应该只有一个数字后缀run_id,而不是两个数字后缀) if [[ "${{ steps.no-expiry.outputs.cache-key }}" =~ -[0-9]+$ ]] && [[ ! "${{ steps.no-expiry.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then echo "✅ 永不过期缓存键格式正确" else echo "❌ 永不过期缓存键格式错误: ${{ steps.no-expiry.outputs.cache-key }}" echo "期望格式: Linux-test-state-no-expiry-test-{run_id}(只有一个数字后缀)" exit 1 fi # 验证过期状态 if [[ "${{ steps.no-expiry.outputs.expired }}" == "false" ]]; then echo "✅ 永不过期缓存过期状态正确" else echo "❌ 永不过期缓存不应显示为过期" exit 1 fi - name: 测试不同过期时间的缓存键差异 run: | echo "🔍 测试不同过期时间的缓存键生成..." # 记录当前时间窗口 CURRENT_TIME=$(date +%s) WINDOW_120=$((CURRENT_TIME / 120)) WINDOW_300=$((CURRENT_TIME / 300)) echo "当前时间: ${CURRENT_TIME}" echo "120秒窗口: ${WINDOW_120}" echo "300秒窗口: ${WINDOW_300}" # 分析已测试的缓存键格式 echo "" echo "📋 已测试的缓存键格式分析:" echo "短期缓存键: ${{ steps.short-expiry.outputs.cache-key }}" echo "永不过期键: ${{ steps.no-expiry.outputs.cache-key }}" # 提取缓存键的最后两个数字段 SHORT_KEY="${{ steps.short-expiry.outputs.cache-key }}" NO_EXPIRY_KEY="${{ steps.no-expiry.outputs.cache-key }}" # 使用sed提取最后的数字段 SHORT_LAST_NUM=$(echo "${SHORT_KEY}" | sed 's/.*-\([0-9]*\)$/\1/') NO_EXPIRY_LAST_NUM=$(echo "${NO_EXPIRY_KEY}" | sed 's/.*-\([0-9]*\)$/\1/') echo "短期缓存最后数字: ${SHORT_LAST_NUM}" echo "永不过期最后数字: ${NO_EXPIRY_LAST_NUM}" # 如果时间窗口不同,说明过期时间影响了缓存键 if [[ ${WINDOW_120} != ${WINDOW_300} ]]; then echo "✅ 不同过期时间产生不同的时间窗口" else echo "ℹ️ 当前时间点两个时间窗口相同(正常情况)" fi - name: 测试额外的过期时间缓存键 id: extra-expiry-test uses: actions/xgj/cache-state@v1 with: state-key: 'extra-expiry-validation' state-value: 'extra-value' default-value: 'extra-default' expiry-seconds: '300' action: 'set' cache-prefix: ${{ inputs.test_prefix }} - name: 验证额外过期测试的缓存键格式 run: | echo "🔍 验证额外过期测试缓存键:" echo "额外过期测试键: ${{ steps.extra-expiry-test.outputs.cache-key }}" # 验证这个缓存键是否有时间窗口 if [[ "${{ steps.extra-expiry-test.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then echo "✅ 额外过期测试缓存键包含时间窗口" else echo "❌ 额外过期测试缓存键缺少时间窗口: ${{ steps.extra-expiry-test.outputs.cache-key }}" fi - name: 测试过期状态判断 id: expiry-check uses: actions/xgj/cache-state@v1 with: state-key: 'non-existent-expiry-test' default-value: 'fallback-value' expiry-seconds: '60' action: 'get' cache-prefix: ${{ inputs.test_prefix }} - name: 验证过期状态判断 run: | echo "🔎 过期状态判断测试结果:" echo "状态值: ${{ steps.expiry-check.outputs.state-value }}" echo "缓存命中: ${{ steps.expiry-check.outputs.cache-hit }}" echo "过期状态: ${{ steps.expiry-check.outputs.expired }}" echo "使用默认值: ${{ steps.expiry-check.outputs.used-default }}" echo "缓存键: ${{ steps.expiry-check.outputs.cache-key }}" # 验证缓存键包含时间窗口 if [[ "${{ steps.expiry-check.outputs.cache-key }}" =~ -[0-9]+-[0-9]+$ ]]; then echo "✅ 过期状态测试缓存键包含时间窗口" else echo "❌ 过期状态测试缓存键缺少时间窗口: ${{ steps.expiry-check.outputs.cache-key }}" exit 1 fi # 因为是新的状态键,应该返回默认值 if [[ "${{ steps.expiry-check.outputs.state-value }}" == "fallback-value" ]]; then echo "✅ 过期测试返回了正确的默认值" else echo "❌ 过期测试没有返回默认值,实际值: ${{ steps.expiry-check.outputs.state-value }}" exit 1 fi # 检查是否正确标记为使用默认值 if [[ "${{ steps.expiry-check.outputs.used-default }}" == "true" ]]; then echo "✅ 正确标记使用了默认值" else echo "❌ 没有正确标记使用默认值: ${{ steps.expiry-check.outputs.used-default }}" exit 1 fi # 对于不存在的缓存且设置了过期时间,过期状态应该是false(因为缓存本身就不存在) if [[ "${{ steps.expiry-check.outputs.cache-hit }}" == "false" && "${{ steps.expiry-check.outputs.expired }}" == "false" ]]; then echo "✅ 正确处理不存在的缓存过期状态" else echo "ℹ️ 过期状态: ${{ steps.expiry-check.outputs.expired }},缓存命中: ${{ steps.expiry-check.outputs.cache-hit }}" echo "ℹ️ 不存在的缓存不应标记为过期,而是未命中" fi - name: 测试各种过期时间值 run: | echo "⏱️ 过期时间功能总结..." echo "" echo "📋 已完成的过期时间测试:" echo "✅ 短期缓存 (120秒): ${{ steps.short-expiry.outputs.cache-key }}" echo "✅ 永不过期 (0秒): ${{ steps.no-expiry.outputs.cache-key }}" echo "✅ 额外测试 (300秒): ${{ steps.extra-expiry-test.outputs.cache-key }}" echo "✅ 过期状态判断 (60秒): ${{ steps.expiry-check.outputs.cache-key }}" echo "" echo "🔍 缓存键格式验证:" # 验证所有带过期时间的缓存键都有时间窗口 KEYS_WITH_EXPIRY=( "${{ steps.short-expiry.outputs.cache-key }}" "${{ steps.extra-expiry-test.outputs.cache-key }}" "${{ steps.expiry-check.outputs.cache-key }}" ) for key in "${KEYS_WITH_EXPIRY[@]}"; do if [[ "$key" =~ -[0-9]+-[0-9]+$ ]]; then echo "✅ $key (包含时间窗口)" else echo "❌ $key (缺少时间窗口)" fi done # 验证永不过期的缓存键 NO_EXPIRY_KEY="${{ steps.no-expiry.outputs.cache-key }}" if [[ "$NO_EXPIRY_KEY" =~ -[0-9]+$ ]] && [[ ! "$NO_EXPIRY_KEY" =~ -[0-9]+-[0-9]+$ ]]; then echo "✅ $NO_EXPIRY_KEY (永不过期,只有run_id)" else echo "❌ $NO_EXPIRY_KEY (永不过期格式错误)" fi echo "" echo "🎯 过期时间功能测试完成!" # 删除功能测试 test-delete-operations: if: ${{ inputs.test_scope == 'delete' || inputs.test_scope == 'full' }} runs-on: ubuntu-node-20 steps: - name: 检出代码 uses: actions/checkout@v4 - name: 设置测试状态 id: setup-delete-test uses: actions/xgj/cache-state@v1 with: state-key: 'delete-test-${{ github.run_id }}' state-value: 'value-to-delete' cache-prefix: ${{ inputs.test_prefix }} action: 'set' - name: 验证状态已设置 id: verify-before-delete uses: actions/xgj/cache-state@v1 with: state-key: 'delete-test-${{ github.run_id }}' default-value: 'not-found' cache-prefix: ${{ inputs.test_prefix }} action: 'get' - name: 验证设置成功 run: | echo "🔍 验证设置成功:" echo "获取的值: ${{ steps.verify-before-delete.outputs.state-value }}" echo "缓存命中: ${{ steps.verify-before-delete.outputs.cache-hit }}" if [[ "${{ steps.verify-before-delete.outputs.cache-hit }}" == "true" && "${{ steps.verify-before-delete.outputs.state-value }}" == "value-to-delete" ]]; then echo "✅ 状态设置验证成功" else echo "❌ 状态设置验证失败" exit 1 fi - name: 执行删除操作 id: delete-operation uses: actions/xgj/cache-state@v1 with: state-key: 'delete-test-${{ github.run_id }}' cache-prefix: ${{ inputs.test_prefix }} action: 'del' - name: 验证删除操作 run: | echo "🗑️ 验证删除操作:" echo "删除标志: ${{ steps.delete-operation.outputs.deleted }}" echo "状态值: ${{ steps.delete-operation.outputs.state-value }}" if [[ "${{ steps.delete-operation.outputs.deleted }}" == "true" ]]; then echo "✅ 删除操作执行成功" else echo "❌ 删除操作标志异常" exit 1 fi if [[ -z "${{ steps.delete-operation.outputs.state-value }}" ]]; then echo "✅ 删除后状态值为空" else echo "❌ 删除后状态值应为空" exit 1 fi - name: 验证删除效果 id: verify-after-delete uses: actions/xgj/cache-state@v1 with: state-key: 'delete-test-${{ github.run_id }}' default-value: 'default-after-delete' cache-prefix: ${{ inputs.test_prefix }} action: 'get' - name: 验证删除生效 run: | echo "🔎 验证删除生效:" echo "获取的值: ${{ steps.verify-after-delete.outputs.state-value }}" echo "缓存命中: ${{ steps.verify-after-delete.outputs.cache-hit }}" echo "使用默认值: ${{ steps.verify-after-delete.outputs.used-default }}" if [[ "${{ steps.verify-after-delete.outputs.cache-hit }}" == "false" && "${{ steps.verify-after-delete.outputs.used-default }}" == "true" ]]; then echo "✅ 删除生效,正确使用默认值" else echo "❌ 删除未生效" exit 1 fi if [[ "${{ steps.verify-after-delete.outputs.state-value }}" == "default-after-delete" ]]; then echo "✅ 获取到正确的默认值" else echo "❌ 默认值不正确" exit 1 fi - name: 测试删除不存在的状态 id: delete-nonexistent uses: actions/xgj/cache-state@v1 with: state-key: 'nonexistent-delete-test-${{ github.run_id }}' cache-prefix: ${{ inputs.test_prefix }} action: 'del' - name: 验证删除不存在状态的行为 run: | echo "🔍 验证删除不存在状态:" echo "删除标志: ${{ steps.delete-nonexistent.outputs.deleted }}" if [[ "${{ steps.delete-nonexistent.outputs.deleted }}" == "true" ]]; then echo "✅ 删除不存在的状态也正确标记为已删除" else echo "❌ 删除不存在状态的标志异常" exit 1 fi - name: 测试删除后重新设置 id: reset-after-delete uses: actions/xgj/cache-state@v1 with: state-key: 'delete-test-${{ github.run_id }}' state-value: 'new-value-after-delete' cache-prefix: ${{ inputs.test_prefix }} action: 'set' - name: 验证删除后重新设置 id: verify-reset uses: actions/xgj/cache-state@v1 with: state-key: 'delete-test-${{ github.run_id }}' default-value: 'should-not-use' cache-prefix: ${{ inputs.test_prefix }} action: 'get' - name: 验证重新设置效果 run: | echo "🔄 验证重新设置效果:" echo "获取的值: ${{ steps.verify-reset.outputs.state-value }}" echo "缓存命中: ${{ steps.verify-reset.outputs.cache-hit }}" if [[ "${{ steps.verify-reset.outputs.cache-hit }}" == "true" && "${{ steps.verify-reset.outputs.state-value }}" == "new-value-after-delete" ]]; then echo "✅ 删除后重新设置成功" else echo "❌ 删除后重新设置失败" exit 1 fi # 错误处理测试 test-error-handling: if: ${{ inputs.test_scope == 'edge-cases' || inputs.test_scope == 'full' }} runs-on: ubuntu-node-20 steps: - name: 检出代码 uses: actions/checkout@v4 - name: 测试无效操作类型 id: invalid-action continue-on-error: true uses: actions/xgj/cache-state@v1 with: state-key: 'error-test-invalid-action' action: 'invalid-action' cache-prefix: ${{ inputs.test_prefix }} - name: 验证错误处理 run: | echo "🚨 验证错误处理..." if [[ "${{ steps.invalid-action.outcome }}" == "failure" ]]; then echo "✅ 无效操作类型正确被拒绝" else echo "❌ 无效操作类型应该失败" exit 1 fi - name: 测试空状态键 id: empty-key continue-on-error: true uses: actions/xgj/cache-state@v1 with: state-key: '' cache-prefix: ${{ inputs.test_prefix }} - name: 验证空键处理 run: | if [[ "${{ steps.empty-key.outcome }}" == "failure" ]]; then echo "✅ 空状态键正确被拒绝" else echo "❌ 空状态键应该失败" exit 1 fi - name: 测试 set 操作无值 id: set-no-value continue-on-error: true uses: actions/xgj/cache-state@v1 with: state-key: 'set-no-value-test' action: 'set' cache-prefix: ${{ inputs.test_prefix }} - name: 验证 set 无值处理 run: | if [[ "${{ steps.set-no-value.outcome }}" == "failure" ]]; then echo "✅ set 操作无值正确被拒绝" else echo "❌ set 操作无值应该失败" exit 1 fi # 清理测试缓存 cleanup-test-cache: if: ${{ inputs.clean_cache && always() }} needs: [test-basic-operations, test-operation-types, test-cache-behavior, test-edge-cases, test-concurrent, test-error-handling] runs-on: ubuntu-node-20 steps: - name: 检出代码 uses: actions/checkout@v4 - name: 清理测试缓存 run: | echo "🧹 清理测试缓存..." # 通过设置空值来清理各种测试缓存 TEST_KEYS=( "basic-test-${{ env.TEST_RUN_ID }}" "get-test-${{ env.TEST_RUN_ID }}" "set-test-${{ env.TEST_RUN_ID }}" "get-or-set-test-${{ env.TEST_RUN_ID }}" "cache-behavior-test-${{ env.TEST_RUN_ID }}" ) for key in "${TEST_KEYS[@]}"; do echo "清理缓存键: ${key}" # 这里可以使用 cache-state action 设置空值来清理 done echo "✅ 测试缓存清理完成" # 测试总结 test-summary: needs: [test-basic-operations, test-operation-types, test-cache-behavior, test-edge-cases, test-expiry, test-delete-operations, test-concurrent, test-error-handling] if: always() runs-on: ubuntu-node-20 steps: - name: 生成测试报告 run: | echo "## 🧪 Cache State Action 测试报告" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### 测试配置" >> $GITHUB_STEP_SUMMARY echo "- **测试范围**: ${{ inputs.test_scope }}" >> $GITHUB_STEP_SUMMARY echo "- **缓存前缀**: ${{ inputs.test_prefix }}" >> $GITHUB_STEP_SUMMARY echo "- **清理缓存**: ${{ inputs.clean_cache }}" >> $GITHUB_STEP_SUMMARY echo "- **运行 ID**: ${{ env.TEST_RUN_ID }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### 测试结果" >> $GITHUB_STEP_SUMMARY # 检查各个任务的结果 if [[ "${{ needs.test-basic-operations.result }}" == "success" ]]; then echo "- ✅ 基础操作测试: 通过" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.test-basic-operations.result }}" == "skipped" ]]; then echo "- ⏭️ 基础操作测试: 跳过" >> $GITHUB_STEP_SUMMARY else echo "- ❌ 基础操作测试: 失败" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.test-operation-types.result }}" == "success" ]]; then echo "- ✅ 操作类型测试: 通过" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.test-operation-types.result }}" == "skipped" ]]; then echo "- ⏭️ 操作类型测试: 跳过" >> $GITHUB_STEP_SUMMARY else echo "- ❌ 操作类型测试: 失败" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.test-cache-behavior.result }}" == "success" ]]; then echo "- ✅ 缓存行为测试: 通过" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.test-cache-behavior.result }}" == "skipped" ]]; then echo "- ⏭️ 缓存行为测试: 跳过" >> $GITHUB_STEP_SUMMARY else echo "- ❌ 缓存行为测试: 失败" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.test-edge-cases.result }}" == "success" ]]; then echo "- ✅ 边界情况测试: 通过" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.test-edge-cases.result }}" == "skipped" ]]; then echo "- ⏭️ 边界情况测试: 跳过" >> $GITHUB_STEP_SUMMARY else echo "- ❌ 边界情况测试: 失败" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.test-concurrent.result }}" == "success" ]]; then echo "- ✅ 并发测试: 通过" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.test-concurrent.result }}" == "skipped" ]]; then echo "- ⏭️ 并发测试: 跳过" >> $GITHUB_STEP_SUMMARY else echo "- ❌ 并发测试: 失败" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.test-expiry.result }}" == "success" ]]; then echo "- ✅ 过期时间测试: 通过" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.test-expiry.result }}" == "skipped" ]]; then echo "- ⏭️ 过期时间测试: 跳过" >> $GITHUB_STEP_SUMMARY else echo "- ❌ 过期时间测试: 失败" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.test-delete-operations.result }}" == "success" ]]; then echo "- ✅ 删除功能测试: 通过" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.test-delete-operations.result }}" == "skipped" ]]; then echo "- ⏭️ 删除功能测试: 跳过" >> $GITHUB_STEP_SUMMARY else echo "- ❌ 删除功能测试: 失败" >> $GITHUB_STEP_SUMMARY fi if [[ "${{ needs.test-error-handling.result }}" == "success" ]]; then echo "- ✅ 错误处理测试: 通过" >> $GITHUB_STEP_SUMMARY elif [[ "${{ needs.test-error-handling.result }}" == "skipped" ]]; then echo "- ⏭️ 错误处理测试: 跳过" >> $GITHUB_STEP_SUMMARY else echo "- ❌ 错误处理测试: 失败" >> $GITHUB_STEP_SUMMARY fi echo "" >> $GITHUB_STEP_SUMMARY echo "### 关键数据" >> $GITHUB_STEP_SUMMARY echo "- **基础测试值**: ${{ needs.test-basic-operations.outputs.test-value }}" >> $GITHUB_STEP_SUMMARY echo "- **基础测试缓存命中**: ${{ needs.test-basic-operations.outputs.cache-hit }}" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### 建议" >> $GITHUB_STEP_SUMMARY echo "- 如果测试失败,请检查 action.yml 中的步骤逻辑" >> $GITHUB_STEP_SUMMARY echo "- 确保 GitHub Actions 缓存功能正常工作" >> $GITHUB_STEP_SUMMARY echo "- 检查特殊字符和 Unicode 的处理" >> $GITHUB_STEP_SUMMARY echo "- 验证并发场景下的缓存一致性" >> $GITHUB_STEP_SUMMARY echo "- 过期时间功能依赖时间窗口机制,注意时区影响" >> $GITHUB_STEP_SUMMARY echo "- 删除功能通过标记实现,被删除的状态会立即失效" >> $GITHUB_STEP_SUMMARY echo "- 缓存最多保存7天,过期时间不会超过此限制" >> $GITHUB_STEP_SUMMARY