Update test data to reflect 0.15 changes
diff --git a/tfexec/internal/e2etest/providers_schema_test.go b/tfexec/internal/e2etest/providers_schema_test.go
index fb9a991..5ba6c80 100644
--- a/tfexec/internal/e2etest/providers_schema_test.go
+++ b/tfexec/internal/e2etest/providers_schema_test.go
@@ -25,31 +25,35 @@
 			"basic", func(tfv *version.Version) *tfjson.ProviderSchemas {
 				var providerSchema *tfjson.ProviderSchemas
 
-				if tfv.LessThan(version.Must(version.NewVersion("0.13.0"))) {
+				if tfv.GreaterThanOrEqual(version.Must(version.NewVersion("0.15.0"))) {
 					providerSchema = &tfjson.ProviderSchemas{
-						FormatVersion: "0.1",
+						FormatVersion: "0.2",
 						Schemas: map[string]*tfjson.ProviderSchema{
-							"null": {
+							"registry.terraform.io/hashicorp/null": {
 								ConfigSchema: &tfjson.Schema{
 									Version: 0,
-									Block:   &tfjson.SchemaBlock{},
+									Block: &tfjson.SchemaBlock{
+										DescriptionKind: "plain",
+									},
 								},
 								ResourceSchemas: map[string]*tfjson.Schema{
 									"null_resource": {
 										Version: 0,
 										Block: &tfjson.SchemaBlock{
-											DescriptionKind: "",
+											DescriptionKind: "markdown",
+											Description:     "The `null_resource` resource implements the standard resource lifecycle but takes no further action.\n\nThe `triggers` argument allows specifying an arbitrary set of values that, when changed, will cause the resource to be replaced.",
 											Attributes: map[string]*tfjson.SchemaAttribute{
 												"id": {
-													AttributeType: cty.String,
-													Optional:      false,
-													Computed:      true,
-													Description:   "This is set to a random value at create time.",
+													AttributeType:   cty.String,
+													Optional:        false,
+													Computed:        true,
+													DescriptionKind: "markdown",
+													Description:     "This is set to a random value at create time.",
 												},
 												"triggers": {
 													AttributeType:   cty.Map(cty.String),
 													Optional:        true,
-													DescriptionKind: "",
+													DescriptionKind: "markdown",
 													Description:     "A map of arbitrary strings that, when changed, will force the null resource to be replaced, re-running any associated provisioners.",
 												},
 											},
@@ -60,48 +64,56 @@
 									"null_data_source": {
 										Version: 0,
 										Block: &tfjson.SchemaBlock{
-											DescriptionKind: "",
-											Description:     "",
+											DescriptionKind: "markdown",
+											Description: `The ` + "`null_data_source`" + ` data source implements the standard data source lifecycle but does not
+interact with any external APIs.
+
+Historically, the ` + "`null_data_source`" + ` was typically used to construct intermediate values to re-use elsewhere in configuration. The
+same can now be achieved using [locals](https://www.terraform.io/docs/language/values/locals.html).
+`,
+											Deprecated: true,
 											Attributes: map[string]*tfjson.SchemaAttribute{
 												"has_computed_default": {
 													AttributeType:   cty.String,
 													Optional:        true,
 													Computed:        true,
-													DescriptionKind: "",
+													DescriptionKind: "markdown",
 													Description:     "If set, its literal value will be stored and returned. If not, its value defaults to `\"default\"`. This argument exists primarily for testing and has little practical use.",
 												},
 												"id": {
 													AttributeType:   cty.String,
 													Optional:        false,
 													Computed:        true,
-													DescriptionKind: "",
+													DescriptionKind: "markdown",
 													Description:     "This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version.",
+													Deprecated:      true,
 												},
 												"inputs": {
 													AttributeType:   cty.Map(cty.String),
 													Optional:        true,
-													DescriptionKind: "",
+													DescriptionKind: "markdown",
 													Description:     "A map of arbitrary strings that is copied into the `outputs` attribute, and accessible directly for interpolation.",
 												},
 												"outputs": {
 													AttributeType:   cty.Map(cty.String),
 													Computed:        true,
-													DescriptionKind: "",
+													DescriptionKind: "markdown",
 													Description:     "After the data source is \"read\", a copy of the `inputs` map.",
 												},
 												"random": {
 													AttributeType:   cty.String,
 													Computed:        true,
-													DescriptionKind: "",
+													DescriptionKind: "markdown",
 													Description:     "A random value. This is primarily for testing and has little practical use; prefer the [hashicorp/random provider](https://registry.terraform.io/providers/hashicorp/random) for more practical random number use-cases.",
 												},
 											},
 										},
 									},
 								},
-							}},
+							},
+						},
 					}
-				} else {
+				} else if tfv.GreaterThanOrEqual(version.Must(version.NewVersion("0.13.0"))) {
 					providerSchema = &tfjson.ProviderSchemas{
 						FormatVersion: "0.1",
 						Schemas: map[string]*tfjson.ProviderSchema{
@@ -186,7 +198,85 @@
 										},
 									},
 								},
-							}},
+							},
+						},
+					}
+				} else {
+					providerSchema = &tfjson.ProviderSchemas{
+						FormatVersion: "0.1",
+						Schemas: map[string]*tfjson.ProviderSchema{
+							"null": {
+								ConfigSchema: &tfjson.Schema{
+									Version: 0,
+									Block:   &tfjson.SchemaBlock{},
+								},
+								ResourceSchemas: map[string]*tfjson.Schema{
+									"null_resource": {
+										Version: 0,
+										Block: &tfjson.SchemaBlock{
+											DescriptionKind: "",
+											Attributes: map[string]*tfjson.SchemaAttribute{
+												"id": {
+													AttributeType: cty.String,
+													Optional:      false,
+													Computed:      true,
+													Description:   "This is set to a random value at create time.",
+												},
+												"triggers": {
+													AttributeType:   cty.Map(cty.String),
+													Optional:        true,
+													DescriptionKind: "",
+													Description:     "A map of arbitrary strings that, when changed, will force the null resource to be replaced, re-running any associated provisioners.",
+												},
+											},
+										},
+									},
+								},
+								DataSourceSchemas: map[string]*tfjson.Schema{
+									"null_data_source": {
+										Version: 0,
+										Block: &tfjson.SchemaBlock{
+											DescriptionKind: "",
+											Description:     "",
+											Attributes: map[string]*tfjson.SchemaAttribute{
+												"has_computed_default": {
+													AttributeType:   cty.String,
+													Optional:        true,
+													Computed:        true,
+													DescriptionKind: "",
+													Description:     "If set, its literal value will be stored and returned. If not, its value defaults to `\"default\"`. This argument exists primarily for testing and has little practical use.",
+												},
+												"id": {
+													AttributeType:   cty.String,
+													Optional:        false,
+													Computed:        true,
+													DescriptionKind: "",
+													Description:     "This attribute is only present for some legacy compatibility issues and should not be used. It will be removed in a future version.",
+												},
+												"inputs": {
+													AttributeType:   cty.Map(cty.String),
+													Optional:        true,
+													DescriptionKind: "",
+													Description:     "A map of arbitrary strings that is copied into the `outputs` attribute, and accessible directly for interpolation.",
+												},
+												"outputs": {
+													AttributeType:   cty.Map(cty.String),
+													Computed:        true,
+													DescriptionKind: "",
+													Description:     "After the data source is \"read\", a copy of the `inputs` map.",
+												},
+												"random": {
+													AttributeType:   cty.String,
+													Computed:        true,
+													DescriptionKind: "",
+													Description:     "A random value. This is primarily for testing and has little practical use; prefer the [hashicorp/random provider](https://registry.terraform.io/providers/hashicorp/random) for more practical random number use-cases.",
+												},
+											},
+										},
+									},
+								},
+							},
+						},
 					}
 				}
 
@@ -194,7 +284,14 @@
 			},
 		},
 		{
-			"empty_with_tf_file", func(*version.Version) *tfjson.ProviderSchemas {
+			"empty_with_tf_file", func(tfv *version.Version) *tfjson.ProviderSchemas {
+				if tfv.GreaterThanOrEqual(version.Must(version.NewVersion("0.15.0"))) {
+					return &tfjson.ProviderSchemas{
+						FormatVersion: "0.2",
+						Schemas:       nil,
+					}
+				}
+
 				return &tfjson.ProviderSchemas{
 					FormatVersion: "0.1",
 					Schemas:       nil,
diff --git a/tfexec/internal/e2etest/validate_test.go b/tfexec/internal/e2etest/validate_test.go
index 307429c..5f49c98 100644
--- a/tfexec/internal/e2etest/validate_test.go
+++ b/tfexec/internal/e2etest/validate_test.go
@@ -55,6 +55,95 @@
 			}
 		}
 
+		var expectedDiags []tfjson.Diagnostic
+
+		if tfv.GreaterThanOrEqual(version.Must(version.NewVersion("0.15.0"))) {
+			expectedDiags = []tfjson.Diagnostic{
+				{
+					Severity: "error",
+					Summary:  "Unsupported block type",
+					Detail:   "Blocks of type \"bad_block\" are not expected here.",
+					Range: &tfjson.Range{
+						Filename: "main.tf",
+						Start: tfjson.Pos{
+							Line:   1,
+							Column: 1,
+						},
+						End: tfjson.Pos{
+							Line:   1,
+							Column: 10,
+						},
+					},
+					Snippet: &tfjson.DiagnosticSnippet{
+						Code:                 "bad_block {",
+						StartLine:            1,
+						HighlightStartOffset: 0,
+						HighlightEndOffset:   9,
+						Values:               []tfjson.DiagnosticExpressionValue{},
+					},
+				},
+				{
+					Severity: "error",
+					Summary:  "Unsupported argument",
+					Detail:   "An argument named \"bad_attribute\" is not expected here.",
+					Range: &tfjson.Range{
+						Filename: "main.tf",
+						Start: tfjson.Pos{
+							Line:   5,
+							Column: 5,
+						},
+						End: tfjson.Pos{
+							Line:   5,
+							Column: 18,
+						},
+					},
+					Snippet: &tfjson.DiagnosticSnippet{
+						Context:              ptrToString("terraform"),
+						Code:                 "    bad_attribute = \"string\"",
+						StartLine:            5,
+						HighlightStartOffset: 4,
+						HighlightEndOffset:   17,
+						Values:               []tfjson.DiagnosticExpressionValue{},
+					},
+				},
+			}
+		} else {
+			expectedDiags = []tfjson.Diagnostic{
+				{
+					Severity: "error",
+					Summary:  "Unsupported block type",
+					Detail:   "Blocks of type \"bad_block\" are not expected here.",
+					Range: &tfjson.Range{
+						Filename: "main.tf",
+						Start: tfjson.Pos{
+							Line:   1,
+							Column: 1,
+						},
+						End: tfjson.Pos{
+							Line:   1,
+							Column: 10,
+						},
+					},
+				},
+				{
+					Severity: "error",
+					Summary:  "Unsupported argument",
+					Detail:   "An argument named \"bad_attribute\" is not expected here.",
+					Range: &tfjson.Range{
+						Filename: "main.tf",
+						Start: tfjson.Pos{
+							Line:   5,
+							Column: 5,
+						},
+						End: tfjson.Pos{
+							Line:   5,
+							Column: 18,
+						},
+					},
+				},
+			}
+		}
+
 		actual, err := tf.Validate(context.Background())
 		if err != nil {
 			t.Fatal(err)
@@ -68,39 +157,10 @@
 			cleanActual = append(cleanActual, diag)
 		}
 
-		assert.Equal(t, []tfjson.Diagnostic{
-			{
-				Severity: "error",
-				Summary:  "Unsupported block type",
-				Detail:   "Blocks of type \"bad_block\" are not expected here.",
-				Range: &tfjson.Range{
-					Filename: "main.tf",
-					Start: tfjson.Pos{
-						Line:   1,
-						Column: 1,
-					},
-					End: tfjson.Pos{
-						Line:   1,
-						Column: 10,
-					},
-				},
-			},
-			{
-				Severity: "error",
-				Summary:  "Unsupported argument",
-				Detail:   "An argument named \"bad_attribute\" is not expected here.",
-				Range: &tfjson.Range{
-					Filename: "main.tf",
-					Start: tfjson.Pos{
-						Line:   5,
-						Column: 5,
-					},
-					End: tfjson.Pos{
-						Line:   5,
-						Column: 18,
-					},
-				},
-			},
-		}, cleanActual)
+		assert.Equal(t, expectedDiags, cleanActual)
 	})
 }
+
+func ptrToString(value string) *string {
+	return &value
+}