1/*
2 *  Copyright 2010 The WebRTC Project Authors. All rights reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11#include <string>
12
13#include "webrtc/base/gunit.h"
14#include "webrtc/base/helpers.h"
15#include "webrtc/base/logging.h"
16#include "webrtc/base/pathutils.h"
17#include "webrtc/base/scoped_ptr.h"
18#include "webrtc/base/multipart.h"
19
20namespace rtc {
21
22static const std::string kTestMultipartBoundary = "123456789987654321";
23static const std::string kTestContentType =
24    "multipart/form-data; boundary=123456789987654321";
25static const char kTestData[] = "This is a test.";
26static const char kTestStreamContent[] = "This is a test stream.";
27
28TEST(MultipartTest, TestBasicOperations) {
29  MultipartStream multipart("multipart/form-data", kTestMultipartBoundary);
30  std::string content_type;
31  multipart.GetContentType(&content_type);
32  EXPECT_EQ(kTestContentType, content_type);
33
34  EXPECT_EQ(rtc::SS_OPENING, multipart.GetState());
35
36  // The multipart stream contains only --boundary--\r\n
37  size_t end_part_size = multipart.GetEndPartSize();
38  multipart.EndParts();
39  EXPECT_EQ(rtc::SS_OPEN, multipart.GetState());
40  size_t size;
41  EXPECT_TRUE(multipart.GetSize(&size));
42  EXPECT_EQ(end_part_size, size);
43
44  // Write is not supported.
45  EXPECT_EQ(rtc::SR_ERROR,
46            multipart.Write(kTestData, sizeof(kTestData), NULL, NULL));
47
48  multipart.Close();
49  EXPECT_EQ(rtc::SS_CLOSED, multipart.GetState());
50  EXPECT_TRUE(multipart.GetSize(&size));
51  EXPECT_EQ(0U, size);
52}
53
54TEST(MultipartTest, TestAddAndRead) {
55  MultipartStream multipart("multipart/form-data", kTestMultipartBoundary);
56
57  size_t part_size =
58      multipart.GetPartSize(kTestData, "form-data; name=\"text\"", "text");
59  EXPECT_TRUE(multipart.AddPart(kTestData, "form-data; name=\"text\"", "text"));
60  size_t size;
61  EXPECT_TRUE(multipart.GetSize(&size));
62  EXPECT_EQ(part_size, size);
63
64  rtc::scoped_ptr<rtc::MemoryStream> stream(
65      new rtc::MemoryStream(kTestStreamContent));
66  size_t stream_size = 0;
67  EXPECT_TRUE(stream->GetSize(&stream_size));
68  part_size +=
69      multipart.GetPartSize("", "form-data; name=\"stream\"", "stream");
70  part_size += stream_size;
71
72  EXPECT_TRUE(multipart.AddPart(
73      new rtc::MemoryStream(kTestStreamContent),
74      "form-data; name=\"stream\"",
75      "stream"));
76  EXPECT_TRUE(multipart.GetSize(&size));
77  EXPECT_EQ(part_size, size);
78
79  // In adding state, block read.
80  char buffer[1024];
81  EXPECT_EQ(rtc::SR_BLOCK,
82            multipart.Read(buffer, sizeof(buffer), NULL, NULL));
83  // Write is not supported.
84  EXPECT_EQ(rtc::SR_ERROR,
85            multipart.Write(buffer, sizeof(buffer), NULL, NULL));
86
87  part_size += multipart.GetEndPartSize();
88  multipart.EndParts();
89  EXPECT_TRUE(multipart.GetSize(&size));
90  EXPECT_EQ(part_size, size);
91
92  // Read the multipart stream into StringStream
93  std::string str;
94  rtc::StringStream str_stream(&str);
95  EXPECT_EQ(rtc::SR_SUCCESS,
96            Flow(&multipart, buffer, sizeof(buffer), &str_stream));
97  EXPECT_EQ(size, str.length());
98
99  // Search three boundaries and two parts in the order.
100  size_t pos = 0;
101  pos = str.find(kTestMultipartBoundary);
102  EXPECT_NE(std::string::npos, pos);
103  pos += kTestMultipartBoundary.length();
104
105  pos = str.find(kTestData, pos);
106  EXPECT_NE(std::string::npos, pos);
107  pos += sizeof(kTestData);
108
109  pos = str.find(kTestMultipartBoundary, pos);
110  EXPECT_NE(std::string::npos, pos);
111  pos += kTestMultipartBoundary.length();
112
113  pos = str.find(kTestStreamContent, pos);
114  EXPECT_NE(std::string::npos, pos);
115  pos += sizeof(kTestStreamContent);
116
117  pos = str.find(kTestMultipartBoundary, pos);
118  EXPECT_NE(std::string::npos, pos);
119  pos += kTestMultipartBoundary.length();
120
121  pos = str.find(kTestMultipartBoundary, pos);
122  EXPECT_EQ(std::string::npos, pos);
123}
124
125}  // namespace rtc
126