Skip to content

Commit

Permalink
fix the UT issue
Browse files Browse the repository at this point in the history
  • Loading branch information
Vivek Yadav authored and akashthawaitcc committed Dec 23, 2024
1 parent df577ef commit 34480de
Show file tree
Hide file tree
Showing 10 changed files with 164 additions and 18 deletions.
14 changes: 12 additions & 2 deletions sources/dynamodb/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ import (
"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface"
"github.com/aws/aws-sdk-go/service/dynamodbstreams"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.uber.org/zap"

"github.com/GoogleCloudPlatform/spanner-migration-tool/internal"
"github.com/GoogleCloudPlatform/spanner-migration-tool/logger"
"github.com/GoogleCloudPlatform/spanner-migration-tool/mocks"
"github.com/GoogleCloudPlatform/spanner-migration-tool/schema"
"github.com/GoogleCloudPlatform/spanner-migration-tool/sources/common"
"github.com/GoogleCloudPlatform/spanner-migration-tool/spanner/ddl"
Expand Down Expand Up @@ -186,10 +188,17 @@ func TestProcessSchema(t *testing.T) {
scanOutputs: scanOutputs,
}
sampleSize := int64(10000)
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})

conv := internal.MakeConv()
processSchema := common.ProcessSchemaImpl{}
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{client, nil, sampleSize}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{client, nil, sampleSize}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})

assert.Nil(t, err)
expectedSchema := map[string]ddl.CreateTable{
Expand Down Expand Up @@ -289,8 +298,9 @@ func TestProcessSchema_FullDataTypes(t *testing.T) {
sampleSize := int64(10000)

conv := internal.MakeConv()
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
processSchema := common.ProcessSchemaImpl{}
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{client, nil, sampleSize}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{client, nil, sampleSize}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})

assert.Nil(t, err)
expectedSchema := map[string]ddl.CreateTable{
Expand Down
21 changes: 19 additions & 2 deletions sources/dynamodb/toddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@
package dynamodb

import (
"context"
"testing"

"github.com/GoogleCloudPlatform/spanner-migration-tool/common/constants"
"github.com/GoogleCloudPlatform/spanner-migration-tool/internal"
"github.com/GoogleCloudPlatform/spanner-migration-tool/mocks"
"github.com/GoogleCloudPlatform/spanner-migration-tool/proto/migration"
"github.com/GoogleCloudPlatform/spanner-migration-tool/schema"
"github.com/GoogleCloudPlatform/spanner-migration-tool/sources/common"
"github.com/GoogleCloudPlatform/spanner-migration-tool/spanner/ddl"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

func TestToSpannerType(t *testing.T) {
Expand Down Expand Up @@ -58,7 +61,14 @@ func TestToSpannerType(t *testing.T) {
}
conv.SrcSchema[name] = srcSchema
conv.Audit = audit
schemaToSpanner := common.SchemaToSpannerImpl{}
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
schemaToSpanner := common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}
assert.Nil(t, schemaToSpanner.SchemaToSpannerDDL(conv, ToDdlImpl{}))
actual := conv.SpSchema[name]
dropComments(&actual) // Don't test comment.
Expand Down Expand Up @@ -119,7 +129,14 @@ func TestToSpannerPostgreSQLDialectType(t *testing.T) {
}
conv.SrcSchema["t1"] = srcSchema
conv.Audit = audit
schemaToSpanner := common.SchemaToSpannerImpl{}
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
schemaToSpanner := common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}
assert.Nil(t, schemaToSpanner.SchemaToSpannerDDL(conv, ToDdlImpl{}))
actual := conv.SpSchema["t1"]
dropComments(&actual) // Don't test comment.
Expand Down
24 changes: 21 additions & 3 deletions sources/mysql/infoschema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@
package mysql

import (
"context"
"database/sql"
"database/sql/driver"
"regexp"
"testing"

"github.com/DATA-DOG/go-sqlmock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"

"github.com/GoogleCloudPlatform/spanner-migration-tool/common/constants"
"github.com/GoogleCloudPlatform/spanner-migration-tool/internal"
"github.com/GoogleCloudPlatform/spanner-migration-tool/mocks"
"github.com/GoogleCloudPlatform/spanner-migration-tool/profiles"
"github.com/GoogleCloudPlatform/spanner-migration-tool/schema"
"github.com/GoogleCloudPlatform/spanner-migration-tool/sources/common"
Expand Down Expand Up @@ -473,7 +476,15 @@ func TestProcessData_MultiCol(t *testing.T) {
conv := internal.MakeConv()
isi := InfoSchemaImpl{"test", db, "migration-project-id", profiles.SourceProfile{}, profiles.TargetProfile{}}
processSchema := common.ProcessSchemaImpl{}
err := processSchema.ProcessSchema(conv, isi, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})

err := processSchema.ProcessSchema(conv, isi, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
assert.Nil(t, err)
expectedSchema := map[string]ddl.CreateTable{
"test": {
Expand All @@ -490,7 +501,7 @@ func TestProcessData_MultiCol(t *testing.T) {
}
internal.AssertSpSchema(conv, t, expectedSchema, stripSchemaComments(conv.SpSchema))
columnLevelIssues := map[string][]internal.SchemaIssue{
"c49": {
"c5": {
2,
},
}
Expand Down Expand Up @@ -576,8 +587,15 @@ func TestProcessSchema_Sharded(t *testing.T) {
db := mkMockDB(t, ms)
conv := internal.MakeConv()
isi := InfoSchemaImpl{"test", db, "migration-project-id", profiles.SourceProfile{}, profiles.TargetProfile{}}
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
processSchema := common.ProcessSchemaImpl{}
err := processSchema.ProcessSchema(conv, isi, 1, internal.AdditionalSchemaAttributes{IsSharded: true}, &common.SchemaToSpannerImpl{}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
err := processSchema.ProcessSchema(conv, isi, 1, internal.AdditionalSchemaAttributes{IsSharded: true}, &common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
assert.Nil(t, err)
expectedSchema := map[string]ddl.CreateTable{
"test": {
Expand Down
21 changes: 19 additions & 2 deletions sources/mysql/toddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
package mysql

import (
"context"
"testing"

"github.com/GoogleCloudPlatform/spanner-migration-tool/common/constants"
"github.com/GoogleCloudPlatform/spanner-migration-tool/internal"
"github.com/GoogleCloudPlatform/spanner-migration-tool/mocks"
"github.com/GoogleCloudPlatform/spanner-migration-tool/schema"
"github.com/GoogleCloudPlatform/spanner-migration-tool/sources/common"
"github.com/GoogleCloudPlatform/spanner-migration-tool/spanner/ddl"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)

func TestToSpannerTypeInternal(t *testing.T) {
Expand Down Expand Up @@ -177,7 +180,14 @@ func TestToSpannerType(t *testing.T) {
PrimaryKeys: []schema.Key{{ColId: "c14"}},
}
conv.UsedNames = map[string]bool{"ref_table": true, "ref_table2": true}
schemaToSpanner := common.SchemaToSpannerImpl{}
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
schemaToSpanner := common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}
assert.Nil(t, schemaToSpanner.SchemaToSpannerDDL(conv, ToDdlImpl{}))
actual := conv.SpSchema[tableId]
dropComments(&actual) // Don't test comment.
Expand Down Expand Up @@ -271,7 +281,14 @@ func TestToSpannerPostgreSQLDialectType(t *testing.T) {
PrimaryKeys: []schema.Key{{ColId: "c14"}},
}
conv.UsedNames = map[string]bool{"ref_table": true, "ref_table2": true}
schemaToSpanner := common.SchemaToSpannerImpl{}
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
schemaToSpanner := common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}
assert.Nil(t, schemaToSpanner.SchemaToSpannerDDL(conv, ToDdlImpl{}))
actual := conv.SpSchema[tableId]
dropComments(&actual) // Don't test comment.
Expand Down
14 changes: 13 additions & 1 deletion sources/oracle/infoschema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@
package oracle

import (
"context"
"database/sql"
"database/sql/driver"
"fmt"
"testing"

"github.com/DATA-DOG/go-sqlmock"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"

"github.com/GoogleCloudPlatform/spanner-migration-tool/internal"
"github.com/GoogleCloudPlatform/spanner-migration-tool/mocks"
"github.com/GoogleCloudPlatform/spanner-migration-tool/profiles"
"github.com/GoogleCloudPlatform/spanner-migration-tool/sources/common"
"github.com/GoogleCloudPlatform/spanner-migration-tool/spanner/ddl"
Expand Down Expand Up @@ -162,7 +165,16 @@ func TestProcessSchemaOracle(t *testing.T) {
db := mkMockDB(t, ms)
conv := internal.MakeConv()
processSchema := common.ProcessSchemaImpl{}
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{"test", db, "migration-project-id", profiles.SourceProfile{}, profiles.TargetProfile{}}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
mockAccessor := new(mocks.MockExpressionVerificationAccessor)

ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})

err := processSchema.ProcessSchema(conv, InfoSchemaImpl{"test", db, "migration-project-id", profiles.SourceProfile{}, profiles.TargetProfile{}}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
assert.Nil(t, err)
expectedSchema := map[string]ddl.CreateTable{
"USER": {
Expand Down
21 changes: 19 additions & 2 deletions sources/oracle/toddl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,18 @@
package oracle

import (
"context"
"testing"

"github.com/GoogleCloudPlatform/spanner-migration-tool/common/constants"
"github.com/GoogleCloudPlatform/spanner-migration-tool/internal"
"github.com/GoogleCloudPlatform/spanner-migration-tool/logger"
"github.com/GoogleCloudPlatform/spanner-migration-tool/mocks"
"github.com/GoogleCloudPlatform/spanner-migration-tool/schema"
"github.com/GoogleCloudPlatform/spanner-migration-tool/sources/common"
"github.com/GoogleCloudPlatform/spanner-migration-tool/spanner/ddl"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -167,7 +170,14 @@ func TestToSpannerType(t *testing.T) {
PrimaryKeys: []schema.Key{{ColId: "c12"}},
}
conv.UsedNames = map[string]bool{"ref_table": true, "ref_table2": true}
schemaToSpanner := common.SchemaToSpannerImpl{}
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
schemaToSpanner := common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}
assert.Nil(t, schemaToSpanner.SchemaToSpannerDDL(conv, ToDdlImpl{}))
actual := conv.SpSchema[tableId]
dropComments(&actual) // Don't test comment.
Expand Down Expand Up @@ -260,7 +270,14 @@ func TestToSpannerPostgreSQLDialectType(t *testing.T) {
PrimaryKeys: []schema.Key{{ColId: "c15"}},
}
conv.UsedNames = map[string]bool{"ref_table": true, "ref_table2": true}
schemaToSpanner := common.SchemaToSpannerImpl{}
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
schemaToSpanner := common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}
assert.Nil(t, schemaToSpanner.SchemaToSpannerDDL(conv, ToDdlImpl{}))
actual := conv.SpSchema[tableId]
dropComments(&actual) // Don't test comment.
Expand Down
21 changes: 19 additions & 2 deletions sources/postgres/infoschema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package postgres

import (
"context"
"database/sql"
"database/sql/driver"
"math/big"
Expand All @@ -26,11 +27,13 @@ import (
"github.com/GoogleCloudPlatform/spanner-migration-tool/common/constants"
"github.com/GoogleCloudPlatform/spanner-migration-tool/internal"
"github.com/GoogleCloudPlatform/spanner-migration-tool/logger"
"github.com/GoogleCloudPlatform/spanner-migration-tool/mocks"
"github.com/GoogleCloudPlatform/spanner-migration-tool/profiles"
"github.com/GoogleCloudPlatform/spanner-migration-tool/schema"
"github.com/GoogleCloudPlatform/spanner-migration-tool/sources/common"
"github.com/GoogleCloudPlatform/spanner-migration-tool/spanner/ddl"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -230,8 +233,15 @@ func TestProcessSchema(t *testing.T) {
}
db := mkMockDB(t, ms)
conv := internal.MakeConv()
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
processSchema := common.ProcessSchemaImpl{}
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{db, "migration-project-id", profiles.SourceProfile{}, profiles.TargetProfile{}, newFalsePtr()}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{db, "migration-project-id", profiles.SourceProfile{}, profiles.TargetProfile{}, newFalsePtr()}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
assert.Nil(t, err)
expectedSchema := map[string]ddl.CreateTable{
"user": ddl.CreateTable{
Expand Down Expand Up @@ -515,8 +525,15 @@ func TestConvertSqlRow_MultiCol(t *testing.T) {
}
db := mkMockDB(t, ms)
conv := internal.MakeConv()
mockAccessor := new(mocks.MockExpressionVerificationAccessor)
ctx := context.Background()
mockAccessor.On("VerifyExpressions", ctx, mock.Anything).Return(internal.VerifyExpressionsOutput{
ExpressionVerificationOutputList: []internal.ExpressionVerificationOutput{
{Result: true, Err: nil, ExpressionDetail: internal.ExpressionDetail{Expression: "(col1 > 0)", Type: "CHECK", Metadata: map[string]string{"tableId": "t1", "colId": "c1", "checkConstraintName": "check1"}, ExpressionId: "expr1"}},
},
})
processSchema := common.ProcessSchemaImpl{}
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{db, "migration-project-id", profiles.SourceProfile{}, profiles.TargetProfile{}, newFalsePtr()}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
err := processSchema.ProcessSchema(conv, InfoSchemaImpl{db, "migration-project-id", profiles.SourceProfile{}, profiles.TargetProfile{}, newFalsePtr()}, 1, internal.AdditionalSchemaAttributes{}, &common.SchemaToSpannerImpl{ExpressionVerificationAccessor: mockAccessor}, &common.UtilsOrderImpl{}, &common.InfoSchemaImpl{})
assert.Nil(t, err)
conv.SetDataMode()
var rows []spannerData
Expand Down
Loading

0 comments on commit 34480de

Please sign in to comment.