ronantakizawa/codereview-bench huggingface dataset:
Repository: opentofu/opentofu
File: internal/tofu/eval_provider_test.go (Go)

Code before:
	if !got.RawEquals(want) {
		t.Fatalf("incorrect merged config\ngot:  %#v\nwant: %#v", got, want)
	}
}

func TestResolveProviderInstance_TypeConversion(t *testing.T) {
	testCases := []struct {
		name        string
		inputValue  cty.Value
		expectedKey string
	}{
		{
			name:        "bool_true_to_string",
			inputValue:  cty.BoolVal(true),
			expectedKey: "true",
		},
		{
			name:        "bool_false_to_string",
			inputValue:  cty.BoolVal(false),
			expectedKey: "false",
		},
		{
			name:        "integer_to_string",
			inputValue:  cty.NumberIntVal(1),
			expectedKey: "1",
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			expr := hcl.StaticExpr(tc.inputValue, hcl.Range{})
			scope := &lang.Scope{
				Data: &evaluationStateData{
					ModulePath:      addrs.RootModuleInstance,
					InstanceKeyData: instances.RepetitionData{},
				},
				BaseDir: ".",
			}
			// call of the function to test
			_, diags := resolveProviderInstance(expr, scope, "test-source")
			if diags.HasErrors() {
				t.Fatalf("Unexpected error: %s", diags.Err())
			}
		})
	}
}


Review comment (suggestion):
I'm sorry I didn't notice this on the first round of review :confounded:  but it doesn't seem like the `expectedKey` fields of these test case definitions are actually used.

Had you intended to compare `expectedKey` to the first result from `resolveProviderInstance`? I think that would be a good idea to make this test more thorough. I would also suggest changing the type of `expectedKey` to be `addrs.InstanceKey` instead of `string`. You can still compare two `addrs.InstanceKey` values using the normal `==` operator, because all implementations of that interface are comparable.


Code after:
	if !got.RawEquals(want) {
		t.Fatalf("incorrect merged config\ngot:  %#v\nwant: %#v", got, want)
	}
}

func TestResolveProviderInstance_TypeConversion(t *testing.T) {
	testCases := []struct {
		name        string
		inputValue  cty.Value
		expectedKey addrs.InstanceKey
	}{
		{
			name:        "bool_true_to_string",
			inputValue:  cty.BoolVal(true),
			expectedKey: addrs.StringKey("true"),
		},
		{
			name:        "bool_false_to_string",
			inputValue:  cty.BoolVal(false),
			expectedKey: addrs.StringKey("false"),
		},
		{
			name:        "integer_to_string",
			inputValue:  cty.NumberIntVal(1),
			expectedKey: addrs.StringKey("1"),
		},
	}

	for _, tc := range testCases {
		t.Run(tc.name, func(t *testing.T) {
			expr := hcl.StaticExpr(tc.inputValue, hcl.Range{})
			scope := &lang.Scope{
				Data: &evaluationStateData{
					ModulePath:      addrs.RootModuleInstance,
					InstanceKeyData: instances.RepetitionData{},
				},
				BaseDir: ".",
			}
			// call of the function to test
			actualKey, diags := resolveProviderInstance(expr, scope, "test-source")

			if diags.HasErrors() {
				t.Fatalf("Unexpected error: %s", diags.Err())
			}

			if actualKey != tc.expectedKey {
				t.Fatalf("Incorrect instance key got:  %#v want: %#v", actualKey, tc.expectedKey)
			}
		})
	}
}
Repository: opentofu/opentofu
File: internal/command/command_test.go (Go)

Code before:
			t.Errorf("missing @timestamp field in log: %s", gotLines[index])
		}
		gotMap = deleteTimestampField(gotMap, "hook", "elapsed_seconds")
		delete(gotMap, "@timestamp")
		gotLineMaps = append(gotLineMaps, gotMap)
	}

	var wantLineMaps []map[string]interface{}
	for i, line := range wantLines[1:] {
		index := i + 1
		var wantMap map[string]interface{}
		if err := json.Unmarshal([]byte(line), &wantMap); err != nil {
			t.Errorf("failed to unmarshal want line %d: %s\n%s", index, err, gotLines[index])
		}
		wantMap = deleteTimestampField(wantMap, "hook", "elapsed_seconds")
		wantLineMaps = append(wantLineMaps, wantMap)
	}

	if diff := cmp.Diff(wantLineMaps, gotLineMaps); diff != "" {
		t.Errorf("wrong output lines\n%s\n"+
			"NOTE: This failure may indicate a UI change affecting the behavior of structured run output on TFC.\n"+
			"Please communicate with Terraform Cloud team before resolving", diff)
	}
}

func deleteTimestampField(fieldMap map[string]interface{}, rootField, field string) map[string]interface{} {
	rootMap, ok := fieldMap[rootField].(map[string]interface{})
	if ok {
		for k := range rootMap {
			if k == field {
				delete(rootMap, field)
			}
		}
		return rootMap
	}
	return fieldMap
}


Review comment (suggestion):
`suggestion`
If we really want to go this path, recommend doing it cleaner, with an early return instead of of this level of nested code.

Code after:
			t.Errorf("missing @timestamp field in log: %s", gotLines[index])
		}
		gotMap = deleteMapField(gotMap, "hook", "elapsed_seconds")
		delete(gotMap, "@timestamp")
		gotLineMaps = append(gotLineMaps, gotMap)
	}

	var wantLineMaps []map[string]interface{}
	for i, line := range wantLines[1:] {
		index := i + 1
		var wantMap map[string]interface{}
		if err := json.Unmarshal([]byte(line), &wantMap); err != nil {
			t.Errorf("failed to unmarshal want line %d: %s\n%s", index, err, gotLines[index])
		}
		wantMap = deleteMapField(wantMap, "hook", "elapsed_seconds")
		wantLineMaps = append(wantLineMaps, wantMap)
	}

	if diff := cmp.Diff(wantLineMaps, gotLineMaps); diff != "" {
		t.Errorf("wrong output lines\n%s\n"+
			"NOTE: This failure may indicate a UI change affecting the behavior of structured run output on TFC.\n"+
			"Please communicate with Terraform Cloud team before resolving", diff)
	}
}

func deleteMapField(fieldMap map[string]interface{}, rootField, field string) map[string]interface{} {
	rootMap, ok := fieldMap[rootField].(map[string]interface{})
	if !ok {
		return fieldMap
	}

	delete(rootMap, field)
	return rootMap
}
Repository: opentofu/opentofu
File: internal/encryption/method/aesgcm/config.go (Go)

Code before:
	AAD []byte `hcl:"aad,optional" json:"aad,omitempty" yaml:"aad,omitempty"`
}

// Build checks the validity of the configuration and returns a ready-to-use AES-GCM implementation.
func (c *Config) Build() (method.Method, hcl.Diagnostics) {
	encryptionKey := c.Keys.EncryptionKey
	decryptionKey := c.Keys.DecryptionKey

	if !validKeyLengths.Has(len(encryptionKey)) {
		return nil, hcl.Diagnostics{
			&hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Invalid configuration for AES-GCM encryption",
				Detail: fmt.Sprintf("AES-GCM requires the key length to be one of: %s, received %d bytes in the decryption key",
					validKeyLengths.String(),
					len(decryptionKey)),
			},
		}
	}

	if len(decryptionKey) > 0 {
		if !validKeyLengths.Has(len(decryptionKey)) {
			return nil, hcl.Diagnostics{
				&hcl.Diagnostic{
					Severity: hcl.DiagError,
					Summary:  "Invalid configuration for AES-GCM encryption",
					Detail: fmt.Sprintf("AES-GCM requires the key length to be one of: %s, received %d bytes in the decryption key",
						validKeyLengths.String(),
						len(decryptionKey)),
				},
			}
		}
	}

	return &aesgcm{
		encryptionKey,
		decryptionKey,
		c.AAD,
	}, nil
}


Review comment (suggestion):
```suggestion
					Summary:  "Invalid configuration for AES-GCM decryption key",
```

Code after:
}

// Build checks the validity of the configuration and returns a ready-to-use AES-GCM implementation.
func (c *Config) Build() (method.Method, error) {
	encryptionKey := c.Keys.EncryptionKey
	decryptionKey := c.Keys.DecryptionKey

	if !validKeyLengths.Has(len(encryptionKey)) {
		return nil, &method.ErrInvalidConfiguration{
			Cause: fmt.Errorf(
				"AES-GCM requires the key length to be one of: %s, received %d bytes in the encryption key",
				validKeyLengths.String(),
				len(encryptionKey),
			),
		}
	}

	if len(decryptionKey) > 0 {
		if !validKeyLengths.Has(len(decryptionKey)) {
			return nil, &method.ErrInvalidConfiguration{
				Cause: fmt.Errorf(
					"AES-GCM requires the key length to be one of: %s, received %d bytes in the decryption key",
					validKeyLengths.String(),
					len(decryptionKey),
				),
			}
		}
	}

	return &aesgcm{
		encryptionKey,
		decryptionKey,
		c.AAD,
	}, nil
}
Repository: opentofu/opentofu
File: internal/encryption/method/aesgcm/compliance_test.go (Go)

Code before:
						return fmt.Errorf("invalid AAD in method after Build()")
					}
					return nil
				},
			},
			"aad": {
				HCL: `method "aes_gcm" "foo" {
						keys = {
							encryption_key = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
							decryption_key = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
						}
						aad = [1,2,3,4]
					}`,
				ValidHCL:   true,
				ValidBuild: true,
				Validate: func(config *Config, method *aesgcm) error {
					if !bytes.Equal(config.AAD, []byte{1, 2, 3, 4}) {
						return fmt.Errorf("invalid AAD in config after HCL parsing")
					}
					if !bytes.Equal(method.aad, []byte{1, 2, 3, 4}) {
						return fmt.Errorf("invalid AAD in method after Build()")
					}
					return nil
				},
			},
			"build-error-type": {
				HCL: `method "aes_gcm" "foo" {
						keys = {
							encryption_key = []
							decryption_key = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
						}
					}`,
				ValidHCL:   true,
				ValidBuild: false,
				Validate:   nil,
			},
		},
		ConfigStructTestCases: map[string]compliancetest.ConfigStructTestCase[*Config, *aesgcm]{
			"empty": {
				Config: &Config{
					Keys: keyprovider.Output{},
					AAD:  nil,
				},
				ValidBuild: false,
				Validate:   nil,
			},
		},
		EncryptDecryptTestCase: compliancetest.EncryptDecryptTestCase[*Config, *aesgcm]{
			ValidEncryptOnlyConfig: &Config{
				Keys: keyprovider.Output{
					EncryptionKey: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},

Review comment (bug):
```suggestion
			"encryption-key-len-fail-on-build": {
```

Or maybe you can find an even better naming here.

Code after:
						return fmt.Errorf("invalid AAD in method after Build()")
					}
					return nil
				},
			},
			"aad": {
				HCL: `method "aes_gcm" "foo" {
						keys = {
							encryption_key = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
							decryption_key = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
						}
						aad = [1,2,3,4]
					}`,
				ValidHCL:   true,
				ValidBuild: true,
				Validate: func(config *Config, method *aesgcm) error {
					if !bytes.Equal(config.AAD, []byte{1, 2, 3, 4}) {
						return fmt.Errorf("invalid AAD in config after HCL parsing")
					}
					if !bytes.Equal(method.aad, []byte{1, 2, 3, 4}) {
						return fmt.Errorf("invalid AAD in method after Build()")
					}
					return nil
				},
			},
			"encryption-key-len-fail-on-build": {
				HCL: `method "aes_gcm" "foo" {
						keys = {
							encryption_key = []
							decryption_key = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
						}
					}`,
				ValidHCL:   true,
				ValidBuild: false,
				Validate:   nil,
			},
		},
		ConfigStructTestCases: map[string]compliancetest.ConfigStructTestCase[*Config, *aesgcm]{
			"empty": {
				Config: &Config{
					Keys: keyprovider.Output{},
					AAD:  nil,
				},
				ValidBuild: false,
				Validate:   nil,
			},
		},
		EncryptDecryptTestCase: compliancetest.EncryptDecryptTestCase[*Config, *aesgcm]{
			ValidEncryptOnlyConfig: &Config{
				Keys: keyprovider.Output{
					EncryptionKey: []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
Repository: opentofu/opentofu
File: internal/encryption/methods.go (Go)

Code before:
	diags = diags.Extend(kpDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	hclCtx, evalDiags := staticEval.EvalContextWithParent(hclCtx, configs.StaticIdentifier{
		Module:    addrs.RootModule,
		Subject:   fmt.Sprintf("encryption.method.%s.%s", cfg.Type, cfg.Name),
		DeclRange: enc.DeclRange,
	}, refs)
	diags = diags.Extend(evalDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	methodDiags := gohcl.DecodeBody(cfg.Body, hclCtx, methodConfig)
	diags = diags.Extend(methodDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	m, methodConfigDiags := methodConfig.Build()
	diags = diags.Extend(methodConfigDiags)


	if diags.HasErrors() {
		return nil, diags
	}

	return m, diags
}


Review comment (suggestion):
```suggestion
	diags = diags.Extend(methodConfigDiags)
	if diags.HasErrors() {
```

Code after:
	diags = diags.Extend(kpDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	hclCtx, evalDiags := staticEval.EvalContextWithParent(hclCtx, configs.StaticIdentifier{
		Module:    addrs.RootModule,
		Subject:   fmt.Sprintf("encryption.method.%s.%s", cfg.Type, cfg.Name),
		DeclRange: enc.DeclRange,
	}, refs)
	diags = diags.Extend(evalDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	methodDiags := gohcl.DecodeBody(cfg.Body, hclCtx, methodConfig)
	diags = diags.Extend(methodDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	m, err := methodConfig.Build()
	if err != nil {
		// Convert the error to a diagnostic
		diags = diags.Append(errorToDiagnostic(err))
	}

	return m, diags
}

func errorToDiagnostic(err error) *hcl.Diagnostic {
	originalErr := err

	for e := err; e != nil; e = errors.Unwrap(e) {
		switch typedErr := e.(type) {
		case *method.ErrEncryptionFailed:
			return &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Encryption operation failed during method setup",
				Detail:   typedErr.Error(),
			}
		case *method.ErrDecryptionFailed:
			return &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Decryption operation failed during method setup",
				Detail:   typedErr.Error(),
			}
		case *method.ErrDecryptionKeyUnavailable:
			return &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Required key unavailable for method setup",
Repository: opentofu/opentofu
File: internal/encryption/methods.go (Go)

Code before:
		return nil, diags
	}

	hclCtx, kpDiags := setupKeyProviders(enc, kpConfigs, meta, reg, staticEval)
	diags = diags.Extend(kpDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	hclCtx, evalDiags := staticEval.EvalContextWithParent(hclCtx, configs.StaticIdentifier{
		Module:    addrs.RootModule,
		Subject:   fmt.Sprintf("encryption.method.%s.%s", cfg.Type, cfg.Name),
		DeclRange: enc.DeclRange,
	}, refs)
	diags = diags.Extend(evalDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	methodDiags := gohcl.DecodeBody(cfg.Body, hclCtx, methodConfig)
	diags = diags.Extend(methodDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	m, methodConfigDiags := methodConfig.Build()
	diags = diags.Extend(methodConfigDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	return m, diags
}


Review comment (bug):
I'm not sure that changing the error to diagnostics from the `Build()` function buys us anything significant at this point.  I also noticed a few bugs introduced when switching from error to diagnostics in this PR (missing summary fields).

Instead, I think we could revert to returning errors and instead make this conversion from error to diagnostic much smarter, based on the type of error returned.

If we make more significant changes to the architecture of the encryption package, we can re-consider the "return error vs diags" in this context.

Code after:
		return nil, diags
	}

	hclCtx, kpDiags := setupKeyProviders(enc, kpConfigs, meta, reg, staticEval)
	diags = diags.Extend(kpDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	hclCtx, evalDiags := staticEval.EvalContextWithParent(hclCtx, configs.StaticIdentifier{
		Module:    addrs.RootModule,
		Subject:   fmt.Sprintf("encryption.method.%s.%s", cfg.Type, cfg.Name),
		DeclRange: enc.DeclRange,
	}, refs)
	diags = diags.Extend(evalDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	methodDiags := gohcl.DecodeBody(cfg.Body, hclCtx, methodConfig)
	diags = diags.Extend(methodDiags)
	if diags.HasErrors() {
		return nil, diags
	}

	m, err := methodConfig.Build()
	if err != nil {
		// Convert the error to a diagnostic
		diags = diags.Append(errorToDiagnostic(err))
	}

	return m, diags
}

func errorToDiagnostic(err error) *hcl.Diagnostic {
	originalErr := err

	for e := err; e != nil; e = errors.Unwrap(e) {
		switch typedErr := e.(type) {
		case *method.ErrEncryptionFailed:
			return &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Encryption operation failed during method setup",
				Detail:   typedErr.Error(),
			}
		case *method.ErrDecryptionFailed:
			return &hcl.Diagnostic{
				Severity: hcl.DiagError,
				Summary:  "Decryption operation failed during method setup",
				Detail:   typedErr.Error(),
			}
Repository: opentofu/opentofu
File: internal/encryption/base.go (Go)

Code before:
		// TODO Discuss if we should potentially cache this based on a json-encoded version of inputData.Meta and reduce overhead dramatically
		decMethod, diags := setupMethod(base.enc.cfg, method, keyProviderMetadata{
			input:  inputData.Meta,
			output: outputData.Meta,
		}, base.enc.reg, base.staticEval)
		if diags.HasErrors() {
			// This cast to error here is safe as we know that at least one error exists
			return nil, StatusUnknown, diags
		}

		uncd, err := decMethod.Decrypt(inputData.Data)
		if err == nil {
			// Success
			if i == 0 {
				// Decrypted with first method (encryption method)
				return uncd, StatusSatisfied, nil
			}
			// Used a fallback
			return uncd, StatusMigration, nil
		}
		// Record the failure
		errs = append(errs, fmt.Errorf("attempted decryption failed for %s: %w", base.name, err))
	}

	errs = append([]error{fmt.Errorf("decryption failed for all provided methods")}, errs...)
	errMessage := errors.Join(errs...).Error()

	return nil, StatusUnknown, errors.New(errMessage)
}


Review comment (suggestion):
We should probably just return the result of errors.Join() here instead of creating a new error below.

Code after:
		// TODO Discuss if we should potentially cache this based on a json-encoded version of inputData.Meta and reduce overhead dramatically
		decMethod, diags := setupMethod(base.enc.cfg, method, keyProviderMetadata{
			input:  inputData.Meta,
			output: outputData.Meta,
		}, base.enc.reg, base.staticEval)
		if diags.HasErrors() {
			// This cast to error here is safe as we know that at least one error exists
			return nil, StatusUnknown, diags
		}

		uncd, err := decMethod.Decrypt(inputData.Data)
		if err == nil {
			// Success
			if i == 0 {
				// Decrypted with first method (encryption method)
				return uncd, StatusSatisfied, nil
			}
			// Used a fallback
			return uncd, StatusMigration, nil
		}
		// Record the failure
		errs = append(errs, fmt.Errorf("attempted decryption failed for %s: %w", base.name, err))
	}

	errs = append([]error{fmt.Errorf("decryption failed for all provided methods")}, errs...)

	return nil, StatusUnknown, errors.New(errors.Join(errs...).Error())
}
Repository: opentofu/opentofu
File: internal/tofu/marks.go (Go)

Code before:
}

// filterNonTargetMarks makes a copy of pvms and then filters out every
// non-target mark and removes the path if it is no longer contains marks.
func filterNonTargetMarks(pvms []cty.PathValueMarks, target interface{}) []cty.PathValueMarks {
	pvmsCopy := make([]cty.PathValueMarks, 0, len(pvms))
	for _, pvm := range pvms {
		pvmsCopy = append(pvmsCopy, copyPathValueMarks(pvm))
	}

	for i := range pvms {
		for k := range pvmsCopy[i].Marks {
			if k != target {
				delete(pvmsCopy[i].Marks, k)
			}
		}

		// Remove PathValueMarks from the slice if there is no
		// marks anymore.
		if len(pvmsCopy[i].Marks) == 0 {
			pvmsCopy = append(pvmsCopy[:i], pvmsCopy[i+1:]...)
		}
	}

	return pvmsCopy
}

// marksEqual compares 2 unordered sets of PathValue marks for equality, with
// the comparison using the cty.PathValueMarks.Equal method.
func marksEqual(a, b []cty.PathValueMarks) bool {
	if len(a) == 0 && len(b) == 0 {
		return true
	}

	if len(a) != len(b) {
		return false
	}

	less := func(s []cty.PathValueMarks) func(i, j int) bool {
		return func(i, j int) bool {
			// the sort only needs to be consistent, so use the GoString format
			// to get a comparable value
			return fmt.Sprintf("%#v", s[i]) < fmt.Sprintf("%#v", s[j])
		}
	}

	sort.Slice(a, less(a))
	sort.Slice(b, less(b))

	for i := 0; i < len(a); i++ {
		if !a[i].Equal(b[i]) {

Review comment (refactor):
I think we could join the two loops and simplify the logic.
```go
	for _, pvm := range pvms {
		cp := copyPathValueMarks(pvm)
		for k := range cp.Marks {
			if k != target {
				delete(cp.Marks, k)
			}
		}
		// Remove PathValueMarks from the slice if there is no
		// marks anymore.
		if len(cp.Marks) == 0 {
			pvmsCopy = append(pvmsCopy, cp)
		}
	}
```

Code after:
}

// filterNonTargetMarks makes a copy of PathValueMarks and filters out every
// non-target mark.
func filterNonTargetMarks(pvms []cty.PathValueMarks, target interface{}) []cty.PathValueMarks {
	pvmsCopy := make([]cty.PathValueMarks, 0, len(pvms))

	for _, pvm := range pvms {
		pvmCopy := copyPathValueMarks(pvm)

		// Remove non-target marks
		for k := range pvm.Marks {
			if k != target {
				delete(pvmCopy.Marks, k)
			}
		}

		// Add path if it still has marks
		if len(pvmCopy.Marks) != 0 {
			pvmsCopy = append(pvmsCopy, pvmCopy)
		}
	}

	return pvmsCopy
}

// marksEqual compares 2 unordered sets of PathValue marks for equality, with
// the comparison using the cty.PathValueMarks.Equal method.
func marksEqual(a, b []cty.PathValueMarks) bool {
	if len(a) == 0 && len(b) == 0 {
		return true
	}

	if len(a) != len(b) {
		return false
	}

	less := func(s []cty.PathValueMarks) func(i, j int) bool {
		return func(i, j int) bool {
			// the sort only needs to be consistent, so use the GoString format
			// to get a comparable value
			return fmt.Sprintf("%#v", s[i]) < fmt.Sprintf("%#v", s[j])
		}
	}

	sort.Slice(a, less(a))
	sort.Slice(b, less(b))

	for i := 0; i < len(a); i++ {
		if !a[i].Equal(b[i]) {
			return false