wal_test.go (etcd-3.5.6) | : | wal_test.go (etcd-3.5.7) | ||
---|---|---|---|---|
skipping to change at line 20 | skipping to change at line 20 | |||
// distributed under the License is distributed on an "AS IS" BASIS, | // distributed under the License is distributed on an "AS IS" BASIS, | |||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
// See the License for the specific language governing permissions and | // See the License for the specific language governing permissions and | |||
// limitations under the License. | // limitations under the License. | |||
package wal | package wal | |||
import ( | import ( | |||
"bytes" | "bytes" | |||
"fmt" | "fmt" | |||
"github.com/stretchr/testify/require" | ||||
"io" | "io" | |||
"io/ioutil" | "io/ioutil" | |||
"math" | "math" | |||
"math/rand" | "math/rand" | |||
"os" | "os" | |||
"path" | "path" | |||
"path/filepath" | "path/filepath" | |||
"reflect" | "reflect" | |||
"regexp" | "regexp" | |||
"testing" | "testing" | |||
skipping to change at line 1158 | skipping to change at line 1159 | |||
files, _, err := selectWALFiles(nil, p, snap0) | files, _, err := selectWALFiles(nil, p, snap0) | |||
if err != nil { | if err != nil { | |||
t.Fatal(err) | t.Fatal(err) | |||
} | } | |||
os.Remove(p + "/" + files[0]) | os.Remove(p + "/" + files[0]) | |||
_, err = ValidSnapshotEntries(zap.NewExample(), p) | _, err = ValidSnapshotEntries(zap.NewExample(), p) | |||
if err != nil { | if err != nil { | |||
t.Fatal(err) | t.Fatal(err) | |||
} | } | |||
} | } | |||
func TestLastRecordLengthExceedFileEnd(t *testing.T) { | ||||
/* The data below was generated by code something like below. The length | ||||
* of the last record was intentionally changed to 1000 in order to make | ||||
* sure it exceeds the end of the file. | ||||
* | ||||
* for i := 0; i < 3; i++ { | ||||
* es := []raftpb.Entry{{Index: uint64(i + 1), Data: []by | ||||
te(fmt.Sprintf("waldata%d", i+1))}} | ||||
* if err = w.Save(raftpb.HardState{}, es); err != n | ||||
il { | ||||
* t.Fatal(err) | ||||
* } | ||||
* } | ||||
* ...... | ||||
* var sb strings.Builder | ||||
* for _, ch := range buf { | ||||
* sb.WriteString(fmt.Sprintf("\\x%02x", ch)) | ||||
* } | ||||
*/ | ||||
// Generate WAL file | ||||
t.Log("Generate a WAL file with the last record's length modified.") | ||||
data := []byte("\x04\x00\x00\x00\x00\x00\x00\x84\x08\x04\x10\x00\x00" + | ||||
"\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x84\x08\x01\x10\x00\x00 | ||||
" + | ||||
"\x00\x00\x00\x0e\x00\x00\x00\x00\x00\x00\x82\x08\x05\x10\xa0\xb3 | ||||
" + | ||||
"\x9b\x8f\x08\x1a\x04\x08\x00\x10\x00\x00\x00\x1a\x00\x00\x00\x00 | ||||
" + | ||||
"\x00\x00\x86\x08\x02\x10\xba\x8b\xdc\x85\x0f\x1a\x10\x08\x00\x10 | ||||
" + | ||||
"\x00\x18\x01\x22\x08\x77\x61\x6c\x64\x61\x74\x61\x31\x00\x00\x00 | ||||
" + | ||||
"\x00\x00\x00\x1a\x00\x00\x00\x00\x00\x00\x86\x08\x02\x10\xa1\xe8 | ||||
" + | ||||
"\xff\x9c\x02\x1a\x10\x08\x00\x10\x00\x18\x02\x22\x08\x77\x61\x6c | ||||
" + | ||||
"\x64\x61\x74\x61\x32\x00\x00\x00\x00\x00\x00\xe8\x03\x00\x00\x00 | ||||
" + | ||||
"\x00\x00\x86\x08\x02\x10\xa1\x9c\xa1\xaa\x04\x1a\x10\x08\x00\x10 | ||||
" + | ||||
"\x00\x18\x03\x22\x08\x77\x61\x6c\x64\x61\x74\x61\x33\x00\x00\x00 | ||||
" + | ||||
"\x00\x00\x00") | ||||
buf := bytes.NewBuffer(data) | ||||
f, err := createFileWithData(t, buf) | ||||
fileName := f.Name() | ||||
require.NoError(t, err) | ||||
t.Logf("fileName: %v", fileName) | ||||
// Verify low-level decoder directly | ||||
t.Log("Verify all records can be parsed correctly.") | ||||
rec := &walpb.Record{} | ||||
decoder := newDecoder(fileutil.NewFileReader(f)) | ||||
for { | ||||
if err = decoder.decode(rec); err != nil { | ||||
require.ErrorIs(t, err, io.ErrUnexpectedEOF) | ||||
break | ||||
} | ||||
if rec.Type == entryType { | ||||
e := mustUnmarshalEntry(rec.Data) | ||||
t.Logf("Validating normal entry: %v", e) | ||||
recData := fmt.Sprintf("waldata%d", e.Index) | ||||
require.Equal(t, raftpb.EntryNormal, e.Type) | ||||
require.Equal(t, recData, string(e.Data)) | ||||
} | ||||
rec = &walpb.Record{} | ||||
} | ||||
require.NoError(t, f.Close()) | ||||
// Verify w.ReadAll() returns io.ErrUnexpectedEOF in the error chain. | ||||
t.Log("Verify the w.ReadAll returns io.ErrUnexpectedEOF in the error chai | ||||
n") | ||||
newFileName := filepath.Join(filepath.Dir(fileName), "0000000000000000-00 | ||||
00000000000000.wal") | ||||
require.NoError(t, os.Rename(fileName, newFileName)) | ||||
w, err := Open(zaptest.NewLogger(t), filepath.Dir(fileName), walpb.Snapsh | ||||
ot{ | ||||
Index: 0, | ||||
Term: 0, | ||||
}) | ||||
require.NoError(t, err) | ||||
defer w.Close() | ||||
_, _, _, err = w.ReadAll() | ||||
// Note: The wal file will be repaired automatically in production | ||||
// environment, but only once. | ||||
require.ErrorIs(t, err, io.ErrUnexpectedEOF) | ||||
} | ||||
End of changes. 2 change blocks. | ||||
0 lines changed or deleted | 1 lines changed or added |