Build number (part after +) is documented as optional, use entire app version if not present (#37036)

diff --git a/packages/flutter_tools/test/general.shard/build_info_test.dart b/packages/flutter_tools/test/general.shard/build_info_test.dart
index e4bc22a..1f12d08 100644
--- a/packages/flutter_tools/test/general.shard/build_info_test.dart
+++ b/packages/flutter_tools/test/general.shard/build_info_test.dart
@@ -17,6 +17,8 @@
     testUsingContext('CFBundleVersion for iOS', () async {
       String buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, 'xyz');
       expect(buildName, '0');
+      buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '0.0.1');
+      expect(buildName, '0.0.1');
       buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '123.xyz');
       expect(buildName, '123');
       buildName = validatedBuildNumberForPlatform(TargetPlatform.ios, '123.456.xyz');
@@ -37,6 +39,8 @@
     testUsingContext('CFBundleShortVersionString for iOS', () async {
       String buildName = validatedBuildNameForPlatform(TargetPlatform.ios, 'xyz');
       expect(buildName, '0.0.0');
+      buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '0.0.1');
+      expect(buildName, '0.0.1');
       buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '123.456.xyz');
       expect(buildName, '123.456.0');
       buildName = validatedBuildNameForPlatform(TargetPlatform.ios, '123.xyz');
diff --git a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart
index d3bb870..231a2b8 100644
--- a/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart
+++ b/packages/flutter_tools/test/general.shard/flutter_manifest_test.dart
@@ -415,6 +415,23 @@
       );
     });
 
+    test('parses major.minor.patch with no build version', () async {
+      const String manifest = '''
+name: test
+version: 0.0.1
+dependencies:
+  flutter:
+    sdk: flutter
+flutter:
+''';
+      await checkManifestVersion(
+        manifest: manifest,
+        expectedAppVersion: '0.0.1',
+        expectedBuildName: '0.0.1',
+        expectedBuildNumber: null,
+      );
+    });
+
     test('parses major.minor.patch+build version clause 2', () async {
       const String manifest = '''
 name: test
diff --git a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
index ec81949..ef36055 100644
--- a/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
+++ b/packages/flutter_tools/test/general.shard/ios/xcodeproj_test.dart
@@ -413,6 +413,7 @@
       final File localPropertiesFile = fs.file('path/to/project/ios/Flutter/Generated.xcconfig');
       expect(propertyFor('FLUTTER_BUILD_NAME', localPropertiesFile), expectedBuildName);
       expect(propertyFor('FLUTTER_BUILD_NUMBER', localPropertiesFile), expectedBuildNumber);
+      expect(propertyFor('FLUTTER_BUILD_NUMBER', localPropertiesFile), isNotNull);
     }
 
     testUsingOsxContext('extract build name and number from pubspec.yaml', () async {
@@ -448,7 +449,7 @@
         manifestString: manifest,
         buildInfo: buildInfo,
         expectedBuildName: '1.0.0',
-        expectedBuildNumber: null,
+        expectedBuildNumber: '1.0.0',
       );
     });
 
@@ -470,6 +471,24 @@
       );
     });
 
+    testUsingOsxContext('allow build info to override build name with build number fallback', () async {
+      const String manifest = '''
+name: test
+version: 1.0.0
+dependencies:
+  flutter:
+    sdk: flutter
+flutter:
+''';
+      const BuildInfo buildInfo = BuildInfo(BuildMode.release, null, buildName: '1.0.2');
+      await checkBuildVersion(
+        manifestString: manifest,
+        buildInfo: buildInfo,
+        expectedBuildName: '1.0.2',
+        expectedBuildNumber: '1.0.2',
+      );
+    });
+
     testUsingOsxContext('allow build info to override build number', () async {
       const String manifest = '''
 name: test