mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 08:54:55 +08:00
fix(tm):建立 Trusted 唯一性与 Supersede 治理
This commit is contained in:
+76
-24
@@ -1023,22 +1023,24 @@ func (f *fakeBackend) TaskCancel(ctx context.Context, taskID string) (*backendrp
|
||||
|
||||
type controlBackend struct {
|
||||
*fakeBackend
|
||||
calls []string
|
||||
parseTextUnitQueries []backendrpc.TextUnitQueryParams
|
||||
parseErrorQueries []backendrpc.TextUnitQueryParams
|
||||
translationTaskUpdates []backendrpc.TranslationTaskUpdateParams
|
||||
translationTaskListParams []backendrpc.TranslationTaskListParams
|
||||
translationMemorySummaryParams []backendrpc.TranslationMemorySummaryParams
|
||||
translationMemoryQueryParams []backendrpc.TranslationMemoryQueryParams
|
||||
translationMemoryConfirmParams []backendrpc.TranslationMemoryConfirmParams
|
||||
glossarySummaryParams []backendrpc.GlossarySummaryParams
|
||||
glossaryQueryParams []backendrpc.GlossaryQueryParams
|
||||
glossaryDiagnoseParams []backendrpc.GlossaryDiagnoseParams
|
||||
glossaryMutationParams []backendrpc.GlossaryTermMutationParams
|
||||
glossaryReviewParams []backendrpc.GlossaryReviewParams
|
||||
glossaryDeleteParams []backendrpc.GlossaryDeleteParams
|
||||
localizedPublishParams []backendrpc.LocalizedPublishParams
|
||||
localizedRollbackParams []backendrpc.LocalizedRollbackParams
|
||||
calls []string
|
||||
parseTextUnitQueries []backendrpc.TextUnitQueryParams
|
||||
parseErrorQueries []backendrpc.TextUnitQueryParams
|
||||
translationTaskUpdates []backendrpc.TranslationTaskUpdateParams
|
||||
translationTaskListParams []backendrpc.TranslationTaskListParams
|
||||
translationMemorySummaryParams []backendrpc.TranslationMemorySummaryParams
|
||||
translationMemoryQueryParams []backendrpc.TranslationMemoryQueryParams
|
||||
translationMemoryConfirmParams []backendrpc.TranslationMemoryConfirmParams
|
||||
translationMemoryConflictsParams []backendrpc.TranslationMemoryConflictsParams
|
||||
translationMemoryResolveParams []backendrpc.TranslationMemoryResolveConflictParams
|
||||
glossarySummaryParams []backendrpc.GlossarySummaryParams
|
||||
glossaryQueryParams []backendrpc.GlossaryQueryParams
|
||||
glossaryDiagnoseParams []backendrpc.GlossaryDiagnoseParams
|
||||
glossaryMutationParams []backendrpc.GlossaryTermMutationParams
|
||||
glossaryReviewParams []backendrpc.GlossaryReviewParams
|
||||
glossaryDeleteParams []backendrpc.GlossaryDeleteParams
|
||||
localizedPublishParams []backendrpc.LocalizedPublishParams
|
||||
localizedRollbackParams []backendrpc.LocalizedRollbackParams
|
||||
}
|
||||
|
||||
func (b *controlBackend) DaemonReload(ctx context.Context) (*backendrpc.Ack, error) {
|
||||
@@ -1183,18 +1185,19 @@ func (b *controlBackend) TranslationProofread(ctx context.Context) (json.RawMess
|
||||
func (b *controlBackend) TranslationMemorySummary(ctx context.Context, params backendrpc.TranslationMemorySummaryParams) (*backendrpc.TranslationMemorySummaryReport, error) {
|
||||
b.calls = append(b.calls, "translation.memory.summary")
|
||||
b.translationMemorySummaryParams = append(b.translationMemorySummaryParams, params)
|
||||
schemaVersion := uint64(1)
|
||||
schemaVersion := uint64(2)
|
||||
return &backendrpc.TranslationMemorySummaryReport{
|
||||
Available: true,
|
||||
Path: params.TranslationMemoryPath,
|
||||
SchemaVersion: &schemaVersion,
|
||||
Summary: &backendrpc.TranslationMemorySummary{
|
||||
SchemaVersion: schemaVersion,
|
||||
RecordCount: 2,
|
||||
TrustedCount: 1,
|
||||
CandidateCount: 1,
|
||||
SupersededCount: 0,
|
||||
RejectedCount: 0,
|
||||
SchemaVersion: schemaVersion,
|
||||
RecordCount: 2,
|
||||
TrustedCount: 1,
|
||||
CandidateCount: 1,
|
||||
SupersededCount: 0,
|
||||
RejectedCount: 0,
|
||||
CurrentTrustedCount: 1,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
@@ -1225,10 +1228,33 @@ func (b *controlBackend) TranslationMemoryConfirm(ctx context.Context, params ba
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *controlBackend) TranslationMemoryConflicts(ctx context.Context, params backendrpc.TranslationMemoryConflictsParams) (*backendrpc.TranslationMemoryConflictsReport, error) {
|
||||
b.calls = append(b.calls, "translation.memory.conflicts")
|
||||
b.translationMemoryConflictsParams = append(b.translationMemoryConflictsParams, params)
|
||||
return &backendrpc.TranslationMemoryConflictsReport{
|
||||
Available: true,
|
||||
Path: params.TranslationMemoryPath,
|
||||
Conflicts: []backendrpc.TranslationMemoryConflict{},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *controlBackend) TranslationMemoryResolveConflict(ctx context.Context, params backendrpc.TranslationMemoryResolveConflictParams) (*backendrpc.TranslationMemoryResolveConflictReport, error) {
|
||||
b.calls = append(b.calls, "translation.memory.resolve_conflict")
|
||||
b.translationMemoryResolveParams = append(b.translationMemoryResolveParams, params)
|
||||
return &backendrpc.TranslationMemoryResolveConflictReport{
|
||||
Available: true,
|
||||
Path: params.TranslationMemoryPath,
|
||||
Entry: backendrpc.TranslationMemoryEntry{
|
||||
RecordID: params.WinnerRecordID,
|
||||
TrustStatus: backendrpc.TranslationMemoryStatusTrusted,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (b *controlBackend) GlossarySummary(ctx context.Context, params backendrpc.GlossarySummaryParams) (*backendrpc.GlossarySummaryReport, error) {
|
||||
b.calls = append(b.calls, "translation.glossary.summary")
|
||||
b.glossarySummaryParams = append(b.glossarySummaryParams, params)
|
||||
schemaVersion := uint64(1)
|
||||
schemaVersion := uint64(2)
|
||||
return &backendrpc.GlossarySummaryReport{
|
||||
Available: true,
|
||||
Path: params.GlossaryPath,
|
||||
@@ -1525,6 +1551,18 @@ func TestAdminTranslationQueryEndpointsProxyAuthenticatedRequests(t *testing.T)
|
||||
t.Fatalf("missing TM query source status=%d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
|
||||
request = httptest.NewRequest(http.MethodGet, "/admin/translation/memory/conflicts?translation_memory_path=%2Fvar%2Flib%2Fbat%2Ftranslation-memory.sqlite&limit=7", nil)
|
||||
request.Header.Set("Authorization", "Bearer translation-token")
|
||||
recorder = httptest.NewRecorder()
|
||||
s.Handler().ServeHTTP(recorder, request)
|
||||
if recorder.Code != http.StatusOK ||
|
||||
len(backend.translationMemoryConflictsParams) != 1 ||
|
||||
backend.translationMemoryConflictsParams[0].TranslationMemoryPath != "/var/lib/bat/translation-memory.sqlite" ||
|
||||
backend.translationMemoryConflictsParams[0].Limit == nil ||
|
||||
*backend.translationMemoryConflictsParams[0].Limit != 7 {
|
||||
t.Fatalf("TM conflicts status=%d body=%s params=%#v", recorder.Code, recorder.Body.String(), backend.translationMemoryConflictsParams)
|
||||
}
|
||||
|
||||
request = httptest.NewRequest(http.MethodGet, "/admin/translation/glossary/summary?glossary_path=%2Fvar%2Flib%2Fbat%2Fglossary.sqlite", nil)
|
||||
request.Header.Set("Authorization", "Bearer translation-token")
|
||||
recorder = httptest.NewRecorder()
|
||||
@@ -2345,6 +2383,7 @@ func TestAdminControlForwardsAllowlistedActions(t *testing.T) {
|
||||
{name: "translation worker run", action: "translation-worker-run", body: `{"provider":"mock","concurrency":8,"max_tasks":2,"retry_backoff_seconds":0,"worker_id":"dashboard-worker"}`, rpcMethod: "translation.worker.run", call: "translation.worker.run"},
|
||||
{name: "translation proofread", action: "translation-proofread", rpcMethod: "translation.proofread", call: "translation.proofread"},
|
||||
{name: "translation memory confirm", action: "translation-memory-confirm", body: `{"record_id":"tm-record-1","reviewer":"reviewer","reason":"reviewed"}`, rpcMethod: "translation.memory.confirm", call: "translation.memory.confirm"},
|
||||
{name: "translation memory resolve conflict", action: "translation-memory-resolve-conflict", body: `{"winner_record_id":"tm-record-1","expected_trusted_record_ids":["tm-record-1","tm-record-2"],"reviewer":"reviewer","reason":"selected"}`, rpcMethod: "translation.memory.resolve_conflict", call: "translation.memory.resolve_conflict"},
|
||||
{name: "translation glossary add", action: "translation-glossary-add", body: `{"term_id":"term-sensei","source_term":"Sensei","recommended_translation":"老师","review_status":"draft","source":{"source_kind":"manual","observed_unix_seconds":100}}`, rpcMethod: "translation.glossary.add", call: "translation.glossary.add"},
|
||||
{name: "translation glossary update", action: "translation-glossary-update", body: `{"term_id":"term-sensei","source_term":"Sensei","recommended_translation":"老师","review_status":"draft","reviewer":"reviewer","source":{"source_kind":"manual","observed_unix_seconds":100}}`, rpcMethod: "translation.glossary.update", call: "translation.glossary.update"},
|
||||
{name: "translation glossary approve", action: "translation-glossary-approve", body: `{"term_id":"term-sensei","reviewer":"reviewer","reason":"approved"}`, rpcMethod: "translation.glossary.approve", call: "translation.glossary.approve"},
|
||||
@@ -2390,6 +2429,11 @@ func TestAdminControlForwardsAllowlistedActions(t *testing.T) {
|
||||
backend.translationMemoryConfirmParams[0].Reviewer != "reviewer" {
|
||||
t.Fatalf("TM confirm params=%#v", backend.translationMemoryConfirmParams)
|
||||
}
|
||||
if len(backend.translationMemoryResolveParams) != 1 ||
|
||||
backend.translationMemoryResolveParams[0].WinnerRecordID != "tm-record-1" ||
|
||||
len(backend.translationMemoryResolveParams[0].ExpectedTrustedRecordIDs) != 2 {
|
||||
t.Fatalf("TM resolve params=%#v", backend.translationMemoryResolveParams)
|
||||
}
|
||||
if len(backend.glossaryMutationParams) != 2 ||
|
||||
backend.glossaryMutationParams[0].TermID != "term-sensei" ||
|
||||
backend.glossaryMutationParams[1].Reviewer != "reviewer" ||
|
||||
@@ -2432,6 +2476,14 @@ func TestAdminControlForwardsAllowlistedActions(t *testing.T) {
|
||||
t.Fatalf("invalid TM confirm status=%d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
|
||||
request = httptest.NewRequest(http.MethodPost, "/admin/control/translation-memory-resolve-conflict", strings.NewReader(`{"winner_record_id":"tm-record-1","expected_trusted_record_ids":["tm-record-1","tm-record-1"],"reviewer":"reviewer","reason":"selected"}`))
|
||||
request.Header.Set("Authorization", "Bearer control-token")
|
||||
recorder = httptest.NewRecorder()
|
||||
s.Handler().ServeHTTP(recorder, request)
|
||||
if recorder.Code != http.StatusBadRequest {
|
||||
t.Fatalf("invalid TM resolve status=%d body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
|
||||
request = httptest.NewRequest(http.MethodPost, "/admin/control/localized-publish", strings.NewReader(`{"from_worker":true,"translation_file":"/tmp/workbench.json"}`))
|
||||
request.Header.Set("Authorization", "Bearer control-token")
|
||||
recorder = httptest.NewRecorder()
|
||||
|
||||
Reference in New Issue
Block a user